From 4718d1b6f95d34188e2a66830c85ed85d2d8f8a7 Mon Sep 17 00:00:00 2001 From: Peter Harrison <16875803+palisadoes@users.noreply.github.com> Date: Thu, 14 Nov 2024 06:56:01 -0800 Subject: [PATCH] Merge with Develop 2024-1-14 (#2656) * 20241114064415 Deleted all files in the main branch in anticipation of merging develop into main cleanly * 20241114064453 Merge develop into main --- .github/dependabot.yaml | 2 +- .github/workflows/codeql-codescan.yml | 3 +- .github/workflows/pull-request.yml | 17 +- .github/workflows/push-documentation.yml | 125 - .github/workflows/push.yml | 5 +- ...y => talawa_api_md_mdx_format_adjuster.py} | 0 INSTALLATION.md | 2 +- README.md | 2 +- codegen.ts | 15 +- config/vitestSetup.ts | 1 - eslint.config.mjs | 165 + locales/en.json | 9 +- locales/fr.json | 9 +- locales/hi.json | 9 +- locales/sp.json | 9 +- locales/zh.json | 9 +- package-lock.json | 21685 +++++++++------- package.json | 63 +- public/markdown/images/recaptcha_set_up.png | Bin 0 -> 165262 bytes public/markdown/images/recaptcha_set_up.webp | Bin 34838 -> 0 bytes renovate.json | 17 + schema.graphql | 354 +- setup.ts | 1 + src/REST/controllers/mutation/createPost.ts | 262 + src/REST/controllers/mutation/index.ts | 2 + src/REST/controllers/mutation/updatePost.ts | 246 + src/REST/controllers/query/getFile.ts | 40 + src/REST/controllers/query/index.ts | 1 + src/REST/routes/index.ts | 31 + src/REST/services/file/createFile.ts | 55 + src/REST/services/file/deleteFile.ts | 35 + src/REST/services/file/index.ts | 3 + src/REST/services/file/uploadFile.ts | 79 + src/REST/services/minio/index.ts | 130 + src/REST/types/index.ts | 9 + src/app.ts | 41 +- src/config/minio/index.ts | 47 + src/config/multer/index.ts | 69 + src/constants.ts | 83 +- src/middleware/fileUpload.ts | 74 + src/middleware/index.ts | 1 + src/middleware/isAuth.ts | 59 +- src/models/ActionItem.ts | 28 +- src/models/{DirectChat.ts => Chat.ts} | 71 +- src/models/ChatMessage.ts | 109 + src/models/Community.ts | 10 + src/models/DirectChatMessage.ts | 78 - src/models/Event.ts | 11 + src/models/EventVolunteer.ts | 95 +- src/models/EventVolunteerGroup.ts | 37 +- src/models/File.ts | 146 +- src/models/GroupChat.ts | 97 - src/models/GroupChatMessage.ts | 75 - src/models/MessageChat.ts | 71 - src/models/OrganizationTagUser.ts | 18 +- src/models/Post.ts | 14 +- src/models/TagUser.ts | 5 + src/models/User.ts | 8 + src/models/VolunteerMembership.ts | 94 + src/models/index.ts | 8 +- src/resolvers/Chat/admins.ts | 14 + src/resolvers/{DirectChat => Chat}/creator.ts | 6 +- src/resolvers/{GroupChat => Chat}/index.ts | 6 +- src/resolvers/Chat/messages.ts | 14 + .../{DirectChat => Chat}/organization.ts | 8 +- src/resolvers/{DirectChat => Chat}/users.ts | 6 +- .../ChatMessage/chatMessageBelongsTo.ts | 25 + src/resolvers/ChatMessage/index.ts | 10 + src/resolvers/ChatMessage/replyTo.ts | 28 + src/resolvers/ChatMessage/sender.ts | 24 + src/resolvers/DirectChat/index.ts | 24 - src/resolvers/DirectChat/messages.ts | 14 - .../directChatMessageBelongsTo.ts | 33 - src/resolvers/DirectChatMessage/index.ts | 10 - src/resolvers/DirectChatMessage/receiver.ts | 34 - src/resolvers/DirectChatMessage/sender.ts | 32 - src/resolvers/Event/actionItems.ts | 2 +- src/resolvers/EventVolunteer/creator.ts | 20 - src/resolvers/EventVolunteer/event.ts | 20 - src/resolvers/EventVolunteer/group.ts | 20 - src/resolvers/EventVolunteer/index.ts | 12 - src/resolvers/EventVolunteer/user.ts | 22 - src/resolvers/EventVolunteerGroup/creator.ts | 22 - src/resolvers/EventVolunteerGroup/event.ts | 20 - src/resolvers/EventVolunteerGroup/index.ts | 10 - src/resolvers/EventVolunteerGroup/leader.ts | 24 - src/resolvers/GroupChat/creator.ts | 20 - src/resolvers/GroupChat/messages.ts | 22 - src/resolvers/GroupChat/organization.ts | 36 - src/resolvers/GroupChat/users.ts | 22 - .../groupChatMessageBelongsTo.ts | 33 - src/resolvers/GroupChatMessage/index.ts | 8 - src/resolvers/GroupChatMessage/sender.ts | 32 - src/resolvers/Mutation/addEventAttendee.ts | 20 +- src/resolvers/Mutation/addPeopleToUserTag.ts | 208 + src/resolvers/Mutation/addUserToGroupChat.ts | 127 - src/resolvers/Mutation/adminRemoveGroup.ts | 132 - src/resolvers/Mutation/assignToUserTags.ts | 174 + src/resolvers/Mutation/assignUserTag.ts | 8 +- src/resolvers/Mutation/createActionItem.ts | 169 +- src/resolvers/Mutation/createChat.ts | 80 + src/resolvers/Mutation/createDirectChat.ts | 62 - .../Mutation/createEventVolunteer.ts | 100 +- .../Mutation/createEventVolunteerGroup.ts | 128 +- src/resolvers/Mutation/createGroupChat.ts | 93 - src/resolvers/Mutation/createMessageChat.ts | 127 - .../Mutation/createVolunteerMembership.ts | 81 + src/resolvers/Mutation/index.ts | 40 +- src/resolvers/Mutation/login.ts | 30 +- src/resolvers/Mutation/removeDirectChat.ts | 81 - .../Mutation/removeEventVolunteer.ts | 91 +- .../Mutation/removeEventVolunteerGroup.ts | 94 +- src/resolvers/Mutation/removeFromUserTags.ts | 165 + src/resolvers/Mutation/removeGroupChat.ts | 80 - src/resolvers/Mutation/removePost.ts | 21 +- .../Mutation/removeUserFromGroupChat.ts | 96 - .../Mutation/sendMembershipRequest.ts | 33 +- src/resolvers/Mutation/sendMessageToChat.ts | 73 + .../Mutation/sendMessageToDirectChat.ts | 71 - .../Mutation/sendMessageToGroupChat.ts | 87 - src/resolvers/Mutation/updateActionItem.ts | 282 +- .../Mutation/updateAgendaCategory.ts | 2 +- .../Mutation/updateEventVolunteer.ts | 82 +- .../Mutation/updateEventVolunteerGroup.ts | 64 +- src/resolvers/Mutation/updatePost.ts | 196 - .../Mutation/updateSessionTimeout.ts | 89 + src/resolvers/Mutation/updateUserProfile.ts | 7 +- .../Mutation/updateVolunteerMembership.ts | 137 + src/resolvers/Organization/image.ts | 8 +- src/resolvers/Organization/posts.ts | 28 +- src/resolvers/Organization/userTags.ts | 45 +- .../Query/actionItemsByOrganization.ts | 30 +- src/resolvers/Query/actionItemsByUser.ts | 109 + src/resolvers/Query/chatById.ts | 26 + src/resolvers/Query/chatsByUserId.ts | 21 + src/resolvers/Query/checkAuth.ts | 8 +- src/resolvers/Query/directChatById.ts | 31 - src/resolvers/Query/directChatsByUserID.ts | 28 - .../Query/directChatsMessagesByChatID.ts | 31 - src/resolvers/Query/eventVolunteersByEvent.ts | 20 - src/resolvers/Query/eventsAttendedByUser.ts | 28 + .../Query/eventsByOrganizationConnection.ts | 19 +- .../Query/getEventVolunteerGroups.ts | 123 +- src/resolvers/Query/getEventVolunteers.ts | 61 + src/resolvers/Query/getRecurringEvents.ts | 25 + src/resolvers/Query/getUserTagAncestors.ts | 45 - src/resolvers/Query/getVolunteerMembership.ts | 129 + src/resolvers/Query/getVolunteerRanks.ts | 146 + src/resolvers/Query/groupChatById.ts | 31 - src/resolvers/Query/groupChatsByUserId.ts | 30 - .../Query/helperFunctions/getSort.ts | 16 + .../Query/helperFunctions/getWhere.ts | 17 +- src/resolvers/Query/index.ts | 29 +- .../Query/organizationsMemberConnection.ts | 8 +- src/resolvers/Query/post.ts | 10 +- src/resolvers/Query/user.ts | 1 - .../Subscription/directMessageChat.ts | 19 - src/resolvers/Subscription/index.ts | 8 +- .../Subscription/messageSentToChat.ts | 43 + .../Subscription/messageSentToDirectChat.ts | 36 - .../Subscription/messageSentToGroupChat.ts | 52 - src/resolvers/User/index.ts | 4 +- src/resolvers/User/tagsAssignedWith.ts | 163 + src/resolvers/UserTag/ancestorTags.ts | 41 + src/resolvers/UserTag/childTags.ts | 40 +- src/resolvers/UserTag/index.ts | 4 + src/resolvers/UserTag/usersAssignedTo.ts | 116 +- src/resolvers/UserTag/usersToAssignTo.ts | 199 + src/resolvers/index.ts | 17 +- src/setup/superAdmin.ts | 3 +- src/typeDefs/enums.ts | 21 + src/typeDefs/errors/createDirectChatError.ts | 16 - src/typeDefs/errors/index.ts | 2 - src/typeDefs/inputs.ts | 120 +- src/typeDefs/mutations.ts | 49 +- src/typeDefs/queries.ts | 41 +- src/typeDefs/subscriptions.ts | 4 +- src/typeDefs/types.ts | 185 +- src/types/generatedGraphQLTypes.ts | 802 +- src/utilities/adminCheck.ts | 19 +- src/utilities/auth.ts | 14 +- src/utilities/checks.ts | 153 + .../encodedImageStorage/deletePreviousFile.ts | 38 + src/utilities/isValidMimeType.ts | 17 + .../getUserTagGraphQLConnectionFilter.ts | 67 + .../getUserTagGraphQLConnectionSort.ts | 45 + ...getUserTagMemberGraphQLConnectionFilter.ts | 81 + .../userTagsPaginationUtils/index.ts | 6 + .../parseUserTagMemberWhere.ts | 73 + .../parseUserTagSortedBy.ts | 50 + .../parseUserTagWhere.ts | 61 + tests/helpers/actionItem.ts | 5 + tests/helpers/chat.ts | 139 + tests/helpers/directChat.ts | 108 - tests/helpers/events.ts | 18 +- tests/helpers/groupChat.ts | 61 - tests/helpers/minio.ts | 49 + tests/helpers/posts.ts | 22 +- tests/helpers/tags.ts | 3 + tests/helpers/userAndOrg.ts | 4 +- tests/helpers/volunteers.ts | 299 + tests/middleware/fileUpload.spec.ts | 215 + tests/middleware/isAuth.spec.ts | 80 +- tests/resolvers/Chat/admins.spec.ts | 42 + .../{DirectChat => Chat}/creator.spec.ts | 18 +- .../{DirectChat => Chat}/messages.spec.ts | 22 +- .../{DirectChat => Chat}/organization.spec.ts | 32 +- .../{DirectChat => Chat}/users.spec.ts | 18 +- .../ChatMessage/chatMessageBelongsTo.spec.ts | 76 + tests/resolvers/ChatMessage/replyTo.spec.ts | 119 + .../sender.spec.ts | 48 +- .../directChatMessageBelongsTo.spec.ts | 75 - .../DirectChatMessage/receiver.spec.ts | 64 - tests/resolvers/Event/actionItems.spec.ts | 2 +- .../resolvers/EventVolunteer/creator.spec.ts | 46 - tests/resolvers/EventVolunteer/event.spec.ts | 38 - tests/resolvers/EventVolunteer/group.spec.ts | 72 - tests/resolvers/EventVolunteer/user.spec.ts | 52 - .../EventVolunteerGroup/creator.spec.ts | 45 - .../EventVolunteerGroup/event.spec.ts | 45 - .../EventVolunteerGroup/leader.spec.ts | 45 - tests/resolvers/GroupChat/creator.spec.ts | 40 - tests/resolvers/GroupChat/messages.spec.ts | 39 - .../resolvers/GroupChat/organization.spec.ts | 46 - tests/resolvers/GroupChat/users.spec.ts | 39 - .../groupChatMessageBelongsTo.spec.ts | 65 - .../resolvers/GroupChatMessage/sender.spec.ts | 64 - .../Mutation/UpdateSessionTimeout.spec.ts | 236 + .../Mutation/addEventAttendee.spec.ts | 157 +- .../Mutation/addPeopleToUserTag.spec.ts | 395 + .../Mutation/addUserToGroupChat.spec.ts | 274 - .../Mutation/adminRemoveGroup.spec.ts | 227 - .../Mutation/assignToUserTags.spec.ts | 322 + .../Mutation/createActionItem.spec.ts | 414 +- ...eDirectChat.spec.ts => createChat.spec.ts} | 66 +- .../Mutation/createEventVolunteer.spec.ts | 28 +- .../createEventVolunteerGroup.spec.ts | 14 +- .../Mutation/createGroupChat.spec.ts | 110 - .../Mutation/createMessageChat.spec.ts | 239 - tests/resolvers/Mutation/createPost.spec.ts | 789 +- .../createVolunteerMembership.spec.ts | 165 + tests/resolvers/Mutation/login.spec.ts | 93 + .../Mutation/removeDirectChat.spec.ts | 228 - .../Mutation/removeEventVolunteer.spec.ts | 134 +- .../removeEventVolunteerGroup.spec.ts | 104 +- .../Mutation/removeFromUserTags.spec.ts | 416 + .../Mutation/removeGroupChat.spec.ts | 243 - .../Mutation/removeOrganization.spec.ts | 1 + tests/resolvers/Mutation/removePost.spec.ts | 113 +- .../Mutation/removeUserFromGroupChat.spec.ts | 228 - .../resolvers/Mutation/removeUserTag.spec.ts | 3 + ...Chat.spec.ts => sendMessageToChat.spec.ts} | 73 +- .../Mutation/sendMessageToGroupChat.spec.ts | 170 - .../Mutation/unassignUserTag.spec.ts | 3 + .../Mutation/updateActionItem.spec.ts | 466 +- .../Mutation/updateEventVolunteer.spec.ts | 225 +- .../updateEventVolunteerGroup.spec.ts | 109 +- tests/resolvers/Mutation/updatePost.spec.ts | 666 +- .../Mutation/updateUserProfile.spec.ts | 94 +- .../updateVolunteerMembership.spec.ts | 175 + tests/resolvers/Organization/image.spec.ts | 2 +- tests/resolvers/Organization/posts.spec.ts | 85 +- tests/resolvers/Organization/userTags.spec.ts | 76 +- .../Query/actionItemsByOrganization.spec.ts | 310 +- .../resolvers/Query/actionItemsByUser.spec.ts | 98 + tests/resolvers/Query/chatById.spec.ts | 37 + tests/resolvers/Query/chatsByuserId.spec.ts | 54 + tests/resolvers/Query/checkAuth.spec.ts | 30 +- tests/resolvers/Query/directChatById.spec.ts | 58 - .../Query/directChatsByUserID.spec.ts | 58 - .../Query/directChatsMessagesByChatID.spec.ts | 96 - .../Query/eventVolunteersByEvent.spec.ts | 40 - .../Query/eventsAttendedByUser.spec.ts | 62 + .../eventsByOrganizationConnection.spec.ts | 55 +- .../Query/getEventVolunteerGroups.spec.ts | 107 +- .../Query/getEventVolunteers.spec.ts | 62 + tests/resolvers/Query/getFile.spec.ts | 138 + .../Query/getRecurringEvents.spec.ts | 118 + tests/resolvers/Query/getUserTag.spec.ts | 6 +- .../Query/getUserTagAncestors.spec.ts | 64 - .../Query/getVolunteerMembership.spec.ts | 170 + .../resolvers/Query/getVolunteerRanks.spec.ts | 100 + tests/resolvers/Query/groupChatById.spec.ts | 61 - .../Query/groupChatsByUserId.spec.ts | 58 - .../Query/helperFunctions/getSort.spec.ts | 10 +- .../Query/helperFunctions/getWhere.spec.ts | 15 +- .../organizationsMemberConnection.spec.ts | 14 +- tests/resolvers/Query/post.spec.ts | 14 +- tests/resolvers/Query/user.spec.ts | 35 +- .../Subscription/directMessageChat.spec.ts | 22 - .../Subscription/messageSentToChat.spec.ts | 88 + .../messageSentToDirectChat.spec.ts | 103 - .../messageSentToGroupChat.spec.ts | 83 - tests/resolvers/User/tagsAssignedWith.spec.ts | 128 + tests/resolvers/UserTag/ancestorTags.spec.ts | 50 + tests/resolvers/UserTag/childTags.spec.ts | 1 - .../resolvers/UserTag/usersAssignedTo.spec.ts | 104 +- .../resolvers/UserTag/usersToAssignTo.spec.ts | 116 + .../middleware/currentUserExists.spec.ts | 1 - tests/services/createFile.spec.ts | 110 + tests/services/deleteFile.spec.ts | 123 + tests/services/uploadFile.spec.ts | 162 + tests/setup/superAdmin.spec.ts | 23 + tests/utilities/adminCheck.spec.ts | 23 +- tests/utilities/auth.spec.ts | 51 +- tests/utilities/checks.spec.ts | 156 + .../createSampleOrganizationUtil.spec.ts | 1 - tests/utilities/deletePreviousFile.spec.ts | 94 + tests/utilities/isValidMimeType.spec.ts | 23 + .../utilities/userTagsPaginationUtils.spec.ts | 350 + 310 files changed, 26054 insertions(+), 19345 deletions(-) delete mode 100644 .github/workflows/push-documentation.yml rename .github/workflows/{md_mdx_format_adjuster.py => talawa_api_md_mdx_format_adjuster.py} (100%) create mode 100644 eslint.config.mjs create mode 100644 public/markdown/images/recaptcha_set_up.png delete mode 100644 public/markdown/images/recaptcha_set_up.webp create mode 100644 renovate.json create mode 100644 src/REST/controllers/mutation/createPost.ts create mode 100644 src/REST/controllers/mutation/index.ts create mode 100644 src/REST/controllers/mutation/updatePost.ts create mode 100644 src/REST/controllers/query/getFile.ts create mode 100644 src/REST/controllers/query/index.ts create mode 100644 src/REST/routes/index.ts create mode 100644 src/REST/services/file/createFile.ts create mode 100644 src/REST/services/file/deleteFile.ts create mode 100644 src/REST/services/file/index.ts create mode 100644 src/REST/services/file/uploadFile.ts create mode 100644 src/REST/services/minio/index.ts create mode 100644 src/REST/types/index.ts create mode 100644 src/config/minio/index.ts create mode 100644 src/config/multer/index.ts create mode 100644 src/middleware/fileUpload.ts rename src/models/{DirectChat.ts => Chat.ts} (51%) create mode 100644 src/models/ChatMessage.ts delete mode 100644 src/models/DirectChatMessage.ts delete mode 100644 src/models/GroupChat.ts delete mode 100644 src/models/GroupChatMessage.ts delete mode 100644 src/models/MessageChat.ts create mode 100644 src/models/VolunteerMembership.ts create mode 100644 src/resolvers/Chat/admins.ts rename src/resolvers/{DirectChat => Chat}/creator.ts (51%) rename src/resolvers/{GroupChat => Chat}/index.ts (57%) create mode 100644 src/resolvers/Chat/messages.ts rename src/resolvers/{DirectChat => Chat}/organization.ts (82%) rename src/resolvers/{DirectChat => Chat}/users.ts (65%) create mode 100644 src/resolvers/ChatMessage/chatMessageBelongsTo.ts create mode 100644 src/resolvers/ChatMessage/index.ts create mode 100644 src/resolvers/ChatMessage/replyTo.ts create mode 100644 src/resolvers/ChatMessage/sender.ts delete mode 100644 src/resolvers/DirectChat/index.ts delete mode 100644 src/resolvers/DirectChat/messages.ts delete mode 100644 src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts delete mode 100644 src/resolvers/DirectChatMessage/index.ts delete mode 100644 src/resolvers/DirectChatMessage/receiver.ts delete mode 100644 src/resolvers/DirectChatMessage/sender.ts delete mode 100644 src/resolvers/EventVolunteer/creator.ts delete mode 100644 src/resolvers/EventVolunteer/event.ts delete mode 100644 src/resolvers/EventVolunteer/group.ts delete mode 100644 src/resolvers/EventVolunteer/index.ts delete mode 100644 src/resolvers/EventVolunteer/user.ts delete mode 100644 src/resolvers/EventVolunteerGroup/creator.ts delete mode 100644 src/resolvers/EventVolunteerGroup/event.ts delete mode 100644 src/resolvers/EventVolunteerGroup/index.ts delete mode 100644 src/resolvers/EventVolunteerGroup/leader.ts delete mode 100644 src/resolvers/GroupChat/creator.ts delete mode 100644 src/resolvers/GroupChat/messages.ts delete mode 100644 src/resolvers/GroupChat/organization.ts delete mode 100644 src/resolvers/GroupChat/users.ts delete mode 100644 src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts delete mode 100644 src/resolvers/GroupChatMessage/index.ts delete mode 100644 src/resolvers/GroupChatMessage/sender.ts create mode 100644 src/resolvers/Mutation/addPeopleToUserTag.ts delete mode 100644 src/resolvers/Mutation/addUserToGroupChat.ts delete mode 100644 src/resolvers/Mutation/adminRemoveGroup.ts create mode 100644 src/resolvers/Mutation/assignToUserTags.ts create mode 100644 src/resolvers/Mutation/createChat.ts delete mode 100644 src/resolvers/Mutation/createDirectChat.ts delete mode 100644 src/resolvers/Mutation/createGroupChat.ts delete mode 100644 src/resolvers/Mutation/createMessageChat.ts create mode 100644 src/resolvers/Mutation/createVolunteerMembership.ts delete mode 100644 src/resolvers/Mutation/removeDirectChat.ts create mode 100644 src/resolvers/Mutation/removeFromUserTags.ts delete mode 100644 src/resolvers/Mutation/removeGroupChat.ts delete mode 100644 src/resolvers/Mutation/removeUserFromGroupChat.ts create mode 100644 src/resolvers/Mutation/sendMessageToChat.ts delete mode 100644 src/resolvers/Mutation/sendMessageToDirectChat.ts delete mode 100644 src/resolvers/Mutation/sendMessageToGroupChat.ts delete mode 100644 src/resolvers/Mutation/updatePost.ts create mode 100644 src/resolvers/Mutation/updateSessionTimeout.ts create mode 100644 src/resolvers/Mutation/updateVolunteerMembership.ts create mode 100644 src/resolvers/Query/actionItemsByUser.ts create mode 100644 src/resolvers/Query/chatById.ts create mode 100644 src/resolvers/Query/chatsByUserId.ts delete mode 100644 src/resolvers/Query/directChatById.ts delete mode 100644 src/resolvers/Query/directChatsByUserID.ts delete mode 100644 src/resolvers/Query/directChatsMessagesByChatID.ts delete mode 100644 src/resolvers/Query/eventVolunteersByEvent.ts create mode 100644 src/resolvers/Query/eventsAttendedByUser.ts create mode 100644 src/resolvers/Query/getEventVolunteers.ts create mode 100644 src/resolvers/Query/getRecurringEvents.ts delete mode 100644 src/resolvers/Query/getUserTagAncestors.ts create mode 100644 src/resolvers/Query/getVolunteerMembership.ts create mode 100644 src/resolvers/Query/getVolunteerRanks.ts delete mode 100644 src/resolvers/Query/groupChatById.ts delete mode 100644 src/resolvers/Query/groupChatsByUserId.ts delete mode 100644 src/resolvers/Subscription/directMessageChat.ts create mode 100644 src/resolvers/Subscription/messageSentToChat.ts delete mode 100644 src/resolvers/Subscription/messageSentToDirectChat.ts delete mode 100644 src/resolvers/Subscription/messageSentToGroupChat.ts create mode 100644 src/resolvers/User/tagsAssignedWith.ts create mode 100644 src/resolvers/UserTag/ancestorTags.ts create mode 100644 src/resolvers/UserTag/usersToAssignTo.ts delete mode 100644 src/typeDefs/errors/createDirectChatError.ts create mode 100644 src/utilities/checks.ts create mode 100644 src/utilities/encodedImageStorage/deletePreviousFile.ts create mode 100644 src/utilities/isValidMimeType.ts create mode 100644 src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionFilter.ts create mode 100644 src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionSort.ts create mode 100644 src/utilities/userTagsPaginationUtils/getUserTagMemberGraphQLConnectionFilter.ts create mode 100644 src/utilities/userTagsPaginationUtils/index.ts create mode 100644 src/utilities/userTagsPaginationUtils/parseUserTagMemberWhere.ts create mode 100644 src/utilities/userTagsPaginationUtils/parseUserTagSortedBy.ts create mode 100644 src/utilities/userTagsPaginationUtils/parseUserTagWhere.ts create mode 100644 tests/helpers/chat.ts delete mode 100644 tests/helpers/directChat.ts delete mode 100644 tests/helpers/groupChat.ts create mode 100644 tests/helpers/minio.ts create mode 100644 tests/helpers/volunteers.ts create mode 100644 tests/middleware/fileUpload.spec.ts create mode 100644 tests/resolvers/Chat/admins.spec.ts rename tests/resolvers/{DirectChat => Chat}/creator.spec.ts (65%) rename tests/resolvers/{DirectChat => Chat}/messages.spec.ts (57%) rename tests/resolvers/{DirectChat => Chat}/organization.spec.ts (61%) rename tests/resolvers/{DirectChat => Chat}/users.spec.ts (59%) create mode 100644 tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts create mode 100644 tests/resolvers/ChatMessage/replyTo.spec.ts rename tests/resolvers/{DirectChatMessage => ChatMessage}/sender.spec.ts (53%) delete mode 100644 tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts delete mode 100644 tests/resolvers/DirectChatMessage/receiver.spec.ts delete mode 100644 tests/resolvers/EventVolunteer/creator.spec.ts delete mode 100644 tests/resolvers/EventVolunteer/event.spec.ts delete mode 100644 tests/resolvers/EventVolunteer/group.spec.ts delete mode 100644 tests/resolvers/EventVolunteer/user.spec.ts delete mode 100644 tests/resolvers/EventVolunteerGroup/creator.spec.ts delete mode 100644 tests/resolvers/EventVolunteerGroup/event.spec.ts delete mode 100644 tests/resolvers/EventVolunteerGroup/leader.spec.ts delete mode 100644 tests/resolvers/GroupChat/creator.spec.ts delete mode 100644 tests/resolvers/GroupChat/messages.spec.ts delete mode 100644 tests/resolvers/GroupChat/organization.spec.ts delete mode 100644 tests/resolvers/GroupChat/users.spec.ts delete mode 100644 tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts delete mode 100644 tests/resolvers/GroupChatMessage/sender.spec.ts create mode 100644 tests/resolvers/Mutation/UpdateSessionTimeout.spec.ts create mode 100644 tests/resolvers/Mutation/addPeopleToUserTag.spec.ts delete mode 100644 tests/resolvers/Mutation/addUserToGroupChat.spec.ts delete mode 100644 tests/resolvers/Mutation/adminRemoveGroup.spec.ts create mode 100644 tests/resolvers/Mutation/assignToUserTags.spec.ts rename tests/resolvers/Mutation/{createDirectChat.spec.ts => createChat.spec.ts} (61%) delete mode 100644 tests/resolvers/Mutation/createGroupChat.spec.ts delete mode 100644 tests/resolvers/Mutation/createMessageChat.spec.ts create mode 100644 tests/resolvers/Mutation/createVolunteerMembership.spec.ts delete mode 100644 tests/resolvers/Mutation/removeDirectChat.spec.ts create mode 100644 tests/resolvers/Mutation/removeFromUserTags.spec.ts delete mode 100644 tests/resolvers/Mutation/removeGroupChat.spec.ts delete mode 100644 tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts rename tests/resolvers/Mutation/{sendMessageToDirectChat.spec.ts => sendMessageToChat.spec.ts} (62%) delete mode 100644 tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts create mode 100644 tests/resolvers/Mutation/updateVolunteerMembership.spec.ts create mode 100644 tests/resolvers/Query/actionItemsByUser.spec.ts create mode 100644 tests/resolvers/Query/chatById.spec.ts create mode 100644 tests/resolvers/Query/chatsByuserId.spec.ts delete mode 100644 tests/resolvers/Query/directChatById.spec.ts delete mode 100644 tests/resolvers/Query/directChatsByUserID.spec.ts delete mode 100644 tests/resolvers/Query/directChatsMessagesByChatID.spec.ts delete mode 100644 tests/resolvers/Query/eventVolunteersByEvent.spec.ts create mode 100644 tests/resolvers/Query/eventsAttendedByUser.spec.ts create mode 100644 tests/resolvers/Query/getEventVolunteers.spec.ts create mode 100644 tests/resolvers/Query/getFile.spec.ts create mode 100644 tests/resolvers/Query/getRecurringEvents.spec.ts delete mode 100644 tests/resolvers/Query/getUserTagAncestors.spec.ts create mode 100644 tests/resolvers/Query/getVolunteerMembership.spec.ts create mode 100644 tests/resolvers/Query/getVolunteerRanks.spec.ts delete mode 100644 tests/resolvers/Query/groupChatById.spec.ts delete mode 100644 tests/resolvers/Query/groupChatsByUserId.spec.ts delete mode 100644 tests/resolvers/Subscription/directMessageChat.spec.ts create mode 100644 tests/resolvers/Subscription/messageSentToChat.spec.ts delete mode 100644 tests/resolvers/Subscription/messageSentToDirectChat.spec.ts delete mode 100644 tests/resolvers/Subscription/messageSentToGroupChat.spec.ts create mode 100644 tests/resolvers/User/tagsAssignedWith.spec.ts create mode 100644 tests/resolvers/UserTag/ancestorTags.spec.ts create mode 100644 tests/resolvers/UserTag/usersToAssignTo.spec.ts create mode 100644 tests/services/createFile.spec.ts create mode 100644 tests/services/deleteFile.spec.ts create mode 100644 tests/services/uploadFile.spec.ts create mode 100644 tests/utilities/checks.spec.ts create mode 100644 tests/utilities/deletePreviousFile.spec.ts create mode 100644 tests/utilities/isValidMimeType.spec.ts create mode 100644 tests/utilities/userTagsPaginationUtils.spec.ts diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 07c49270a0..9a3e9a54e9 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -7,7 +7,7 @@ updates: directory: "/" # Schedule automated updates to run weekly schedule: - interval: "weekly" + interval: "monthly" # Labels to apply to Dependabot PRs labels: - "dependencies" diff --git a/.github/workflows/codeql-codescan.yml b/.github/workflows/codeql-codescan.yml index 272e67db8b..95f6c2b13a 100644 --- a/.github/workflows/codeql-codescan.yml +++ b/.github/workflows/codeql-codescan.yml @@ -21,7 +21,8 @@ on: jobs: CodeQL: - name: CodeQL + if: ${{ github.actor != 'dependabot[bot]' }} + name: Analyse Code With CodeQL runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 10fd9fd62f..44b5939049 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -37,7 +37,7 @@ jobs: - name: Count number of lines run: | chmod +x ./.github/workflows/countline.py - ./.github/workflows/countline.py --lines 600 --exclude_files src/types/generatedGraphQLTypes.ts tests src/typeDefs/types.ts src/constants.ts + ./.github/workflows/countline.py --lines 600 --exclude_files src/types/generatedGraphQLTypes.ts tests src/typeDefs/types.ts src/constants.ts src/typeDefs/inputs.ts - name: Check for TSDoc comments run: npm run check-tsdoc # Run the TSDoc check script @@ -90,8 +90,9 @@ jobs: echo "Error: Source and Target Branches are the same. Please ensure they are different." exit 1 - Check-Unauthorized-Changes: - name: Checks if no unauthorized files are changed + Check-Sensitive-Files: + if: ${{ github.actor != 'dependabot[bot]' && !contains(github.event.pull_request.labels.*.name, 'ignore-sensitive-files-pr') }} + name: Checks if sensitive files have been changed without authorization runs-on: ubuntu-latest steps: - name: Checkout code @@ -126,6 +127,13 @@ jobs: setup.ts schema.graphql .coderabbit.yaml + CODE_OF_CONDUCT.md + CONTRIBUTING.md + DOCUMENTATION.md + INSTALLATION.md + ISSUE_GUIDELINES.md + PR_GUIDELINES.md + README.md - name: List all changed unauthorized files if: steps.changed-unauth-files.outputs.any_changed == 'true' || steps.changed-unauth-files.outputs.any_deleted == 'true' @@ -138,6 +146,7 @@ jobs: exit 1 File-count-check: + if: ${{ github.actor != 'dependabot[bot]' }} name: Checks if number of files changed is acceptable runs-on: ubuntu-latest steps: @@ -288,6 +297,7 @@ jobs: min_coverage: 95.0 JSDocs: + if: ${{ github.actor != 'dependabot[bot]' }} name: 'JSDocs comments and pipeline' runs-on: ubuntu-latest needs: Test-Application @@ -303,6 +313,7 @@ jobs: run: echo "Run JSdocs :${{ env.RUN_JSDOCS }}" Branch-check: + if: ${{ github.actor != 'dependabot[bot]' }} name: "Base branch check" runs-on: ubuntu-latest steps: diff --git a/.github/workflows/push-documentation.yml b/.github/workflows/push-documentation.yml deleted file mode 100644 index 45430983df..0000000000 --- a/.github/workflows/push-documentation.yml +++ /dev/null @@ -1,125 +0,0 @@ -############################################################################## -############################################################################## -# -# NOTE! -# -# Please read the README.md file in this directory that defines what should -# be placed in this file -# -############################################################################## -############################################################################## - -name: Push Documentation Workflow - -on: - push: - branches-ignore: - - '*' - -jobs: - ############################################################################## - # This section is added so that the Talawa Docs repository and Talawa API - # are both updated with the latest schema docs post merge. - ############################################################################## - - Push-Workflow: - name: Updating Documentation - runs-on: ubuntu-latest - environment: TALAWA_ENVIRONMENT - strategy: - matrix: - node-version: [20.x] - services: - mongo: - image: mongo:4.4 - options: >- - --health-cmd mongo - --health-interval 10s - --health-timeout 5s - --health-retries 10 - ports: - - 27017:27017 - env: - MONGO_DB_URL: mongodb://localhost:27017/talawa-test-db -# ACCESS_TOKEN_SECRET: ${{ secrets.ACCESS_TOKEN_SECRET }} -# REFRESH_TOKEN_SECRET: ${{ secrets.REFRESH_TOKEN_SECRET }} - - # We checkout the content of the Talawa-API repository in a directory called `api` - # This is done as we will use the Talawa-Docs repository later too - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - token: ${{ secrets.TALAWA_DOCS_SYNC }} - path: api - - - name: Generate Access Token Secret - run: echo "ACCESS_TOKEN_SECRET=$(openssl rand -hex 32)" >> $GITHUB_ENV - - - name: Generate Refresh Token Secret - run: echo "REFRESH_TOKEN_SECRET=$(openssl rand -hex 32)" >> $GITHUB_ENV - - - name: Set up Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - - # Move into the api folder before installing the dependencies - - name: Install dependencies - run: cd api && npm ci - - # Move into the api folder before starting the server - - name: Start the development server in detach mode - run: | - cd api && npm run dev & - echo "Development server started..." - - # Sleep for 10 s - - name: Sleep for 10s - uses: juliangruber/sleep-action@v2 - with: - time: 10s - - # Move into the api folder before generating the Markdown schema documentation - - name: Generate the GraphQL-Markdown documentation - run: cd api && npm run generate:graphql-markdown - - # Move into the api folder before generating the Schema is json form - - name: Genrate the GraphQL Schema in JSON form - run: cd api && npm run generate:graphql-schema - - - # Running the generate::** scripts will create the necessary documentation on the server - # where the GitHub Action is running locally. We add the same to stage with -f flag as they are a - # part of the .gitignore file - - name: Add the generated Markdown Documentation to stage - run: cd api && git add docs/Schema.md -f - - # We use this action to commit the changes above to the repository - - name: Commit generated Markdown Documentation to the Talawa API repository - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: Generate GraphQL Schema and Markdown Documentation - repository: api - - # We will clone the Talawa Docs in the folder called docs so that we can copy the generated - # schema.json into the same later - - name: Checkout the Talawa-Docs repository - uses: actions/checkout@v4 - with: - repository: PalisadoesFoundation/talawa-docs - token: ${{ secrets.TALAWA_DOCS_SYNC }} - path: docs - - # Copy the generated schema.json into the Talawa Docs repository - - name: Sync schema.json from Talawa API to Talawa Docs - run: cp api/docs/schema.json docs/docs/github-actions/ - - # Add the updated schema.json in Talawa Docs to stage - - name: Add the synced schema.json to stage in Talawa Docs - run: cd docs && git add docs/github-actions/schema.json - - # Commit the changes made to schema.json into Talawa Docs - - name: Commit the synced schema to the Talawa Docs repository - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: Update schema.json - repository: docs diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 90c6dfbcf7..d94f50a3d8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -26,6 +26,7 @@ jobs: ############################################################################## Push-Workflow: + if: ${{ github.actor != 'dependabot[bot]' }} name: Testing Application runs-on: ubuntu-latest strategy: @@ -54,8 +55,6 @@ jobs: MONGO_DB_URL: mongodb://localhost:27017/talawa-test-db REDIS_HOST: localhost REDIS_PORT: 6379 -# ACCESS_TOKEN_SECRET: ${{ secrets.ACCESS_TOKEN_SECRET }} -# REFRESH_TOKEN_SECRET: ${{ secrets.REFRESH_TOKEN_SECRET }} # We checkout the content of the Talawa-API repository in a directory called `api` steps: @@ -95,6 +94,7 @@ jobs: # You can find the deployment instructions in the scripts/cloud-api-demo/README.md file Deploy-Workflow: + if: ${{ github.actor != 'dependabot[bot]' }} name: Deploying Application to Cloud VPS needs: Push-Workflow runs-on: ubuntu-latest @@ -130,6 +130,7 @@ jobs: python3 /usr/local/bin/scripts/deploy.py --path ~/develop --branch develop Check-Schema: + if: ${{ github.actor != 'dependabot[bot]' }} name: Check Schema runs-on: ubuntu-latest diff --git a/.github/workflows/md_mdx_format_adjuster.py b/.github/workflows/talawa_api_md_mdx_format_adjuster.py similarity index 100% rename from .github/workflows/md_mdx_format_adjuster.py rename to .github/workflows/talawa_api_md_mdx_format_adjuster.py diff --git a/INSTALLATION.md b/INSTALLATION.md index 583dd18ace..7eee20568f 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -836,7 +836,7 @@ We use `reCAPTCHA` for two factor authentication (2FA). Follow these steps: 1. Visit the [reCAPTCHA Key Generation](https://www.google.com/recaptcha/admin/create) URL. 1. Fill in the input blocks as shown in the screenshot: - ![Set up recaptcha page](public/markdown/images/recaptcha_set_up.webp) + ![Set up recaptcha page](public/markdown/images/recaptcha_set_up.png) 1. Click on `Submit` button. 1. Copy the generated `Secret Key` to variable named `RECAPTCHA_SECRET_KEY` in `.env` file. diff --git a/README.md b/README.md index bdf939c79f..ddf41d33ec 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Core features include: `talawa` is based on the original `quito` code created by the [Palisadoes Foundation](http://www.palisadoes.org) as part of its annual Calico Challenge program. Calico provides paid summer internships for Jamaican university students to work on selected open source projects. They are mentored by software professionals and receive stipends based on the completion of predefined milestones. Calico was started in 2015. Visit [The Palisadoes Foundation's website](http://www.palisadoes.org/) for more details on its origin and activities. -## Table of Contents +## Table of Contents diff --git a/codegen.ts b/codegen.ts index 75bbf9f1c6..9a34f09b9b 100644 --- a/codegen.ts +++ b/codegen.ts @@ -40,16 +40,13 @@ const config: CodegenConfig = { CheckIn: "../models/CheckIn#InterfaceCheckIn", - MessageChat: "../models/MessageChat#InterfaceMessageChat", - Comment: "../models/Comment#InterfaceComment", Community: "../models/Community#InterfaceCommunity", - DirectChat: "../models/DirectChat#InterfaceDirectChat", + Chat: "../models/Chat#InterfaceChat", - DirectChatMessage: - "../models/DirectChatMessage#InterfaceDirectChatMessage", + ChatMessage: "../models/ChatMessage#InterfaceChatMessage", Donation: "../models/Donation#InterfaceDonation", @@ -75,11 +72,6 @@ const config: CodegenConfig = { Group: "../models/Group#InterfaceGroup", - GroupChat: "../models/GroupChat#InterfaceGroupChat", - - GroupChatMessage: - "../models/GroupChatMessage#InterfaceGroupChatMessage", - // ImageHash: '../models/ImageHash#InterfaceImageHash', Language: "../models/Language#InterfaceLanguage", @@ -106,6 +98,9 @@ const config: CodegenConfig = { User: "../models/User#InterfaceUser", Venue: "../models/Venue#InterfaceVenue", + + VolunteerMembership: + "../models/VolunteerMembership#InterfaceVolunteerMembership", }, useTypeImports: true, diff --git a/config/vitestSetup.ts b/config/vitestSetup.ts index 44152f1a19..3be116e90c 100644 --- a/config/vitestSetup.ts +++ b/config/vitestSetup.ts @@ -1,6 +1,5 @@ // FAIL LOUDLY on unhandled promise rejections / errors process.on("unhandledRejection", (reason) => { - // eslint-disable-next-line no-console console.log("FAILED TO HANDLE PROMISE REJECTION"); throw reason; }); diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..16ddae464e --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,165 @@ +import typescriptEslint from "@typescript-eslint/eslint-plugin"; +import tsdoc from "eslint-plugin-tsdoc"; +import _import from "eslint-plugin-import"; +import { fixupPluginRules } from "@eslint/compat"; +import globals from "globals"; +import tsParser from "@typescript-eslint/parser"; +import * as parser from "@graphql-eslint/eslint-plugin"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; +import * as graphqlEslint from "@graphql-eslint/eslint-plugin"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended +}); + +export default [ + { + ignores: [ + "**/.github", + "**/.vscode", + "**/build", + "**/coverage", + "**/node_modules", + "src/types", + "docs/Schema.md", + ], + }, + ...compat.extends( + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + ), + { + plugins: { + "@typescript-eslint": typescriptEslint, + tsdoc, + import: fixupPluginRules(_import), + }, + + languageOptions: { + parser: tsParser, + globals: { + ...globals.node, + }, + }, + rules: { + "no-restricted-imports": [ + "error", + { + patterns: ["**/src/**"], + }, + ], + "import/no-duplicates": "error", + "tsdoc/syntax": "error", + "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/no-empty-object-type": "error", + "@typescript-eslint/no-unsafe-function-type": "error", + "@typescript-eslint/no-wrapper-object-types": "error", + "@typescript-eslint/no-duplicate-enum-values": "error", + "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-non-null-asserted-optional-chain": "error", + "@typescript-eslint/no-non-null-assertion": "error", + "@typescript-eslint/no-var-requires": "error", + }, + }, + { + files: ["**/*.ts"], + + languageOptions: { + parser: tsParser, + ecmaVersion: "latest", + sourceType: "module", + + parserOptions: { + project: "./tsconfig.json", + tsconfigRootDir: ".", + }, + }, + + rules: { + "@typescript-eslint/array-type": "error", + "@typescript-eslint/consistent-type-assertions": "error", + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/explicit-function-return-type": "error", + + "@typescript-eslint/naming-convention": [ + "error", + { + selector: "interface", + format: ["PascalCase"], + prefix: ["Interface", "TestInterface"], + }, + { + selector: ["typeAlias", "typeLike", "enum"], + format: ["PascalCase"], + }, + { + selector: "typeParameter", + format: ["PascalCase"], + prefix: ["T"], + }, + { + selector: "variable", + format: ["camelCase", "UPPER_CASE"], + leadingUnderscore: "allow", + }, + { + selector: "parameter", + format: ["camelCase"], + leadingUnderscore: "allow", + }, + { + selector: "function", + format: ["camelCase"], + }, + { + selector: "memberLike", + modifiers: ["private"], + format: ["camelCase"], + leadingUnderscore: "require", + }, + { + selector: "variable", + modifiers: ["exported"], + format: null, + }, + ], + }, + }, + { + files: ["./src/typeDefs/**/*.ts"], + processor: "@graphql-eslint/graphql", + }, + { + files: ["./src/typeDefs/**/*.graphql"], + + plugins: { + "@graphql-eslint": graphqlEslint, + }, + + languageOptions: { + parser: graphqlEslint.parser, + }, + }, + { + files: ["tests/**/*"], + + rules: { + "no-restricted-imports": "off", + }, + }, + { + files: ["./src/index.ts", "./src/utilities/copyToClipboard.ts"], + + rules: { + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-empty-function": "off", + }, + }, +]; diff --git a/locales/en.json b/locales/en.json index 1769c40537..15dcd74f54 100644 --- a/locales/en.json +++ b/locales/en.json @@ -29,10 +29,17 @@ "invalid.fileType": "Invalid file type", "invalid.refreshToken": "Invalid refresh token", "invalid.credentials": "Invalid credentials", + "invalid.timeoutRange": "Invalid timeout range", "registrant.alreadyExist": "Already registered for the event", "member.notFound": "Member not found", "registrant.alreadyUnregistered": "Already unregistered for the event", "translation.alreadyPresent": "Translation Already Present", "translation.notFound": "Translation not found", - "parameter.missing": "Missing Skip parameter. Set it to either 0 or some other value not found" + "parameter.missing": "Missing Skip parameter. Set it to either 0 or some other value not found", + "tag.alreadyExists": "A tag with the same name already exists at this level", + "invalid.contentType": "Invalid content type. Expected multipart/form-data", + "invalid.fieldFileName": "Invalid file input field name received", + "file.sizeExceeded": "File size exceeds the allowable limit", + "file.notFound": "File not found.", + "invalid.argument": "Invalid argument received" } diff --git a/locales/fr.json b/locales/fr.json index 39fea9082c..07eb2be24f 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -28,10 +28,17 @@ "invalid.fileType": "Type de fichier non valide", "invalid.refreshToken": "Jeton d'actualisation non valide", "invalid.credentials": "Informations d'identification non valides", + "invalid.timeoutRange": "Plage de temps d'attente non valide", "registrant.alreadyExist": "Déjà inscrit à l'événement", "member.notFound": "Membre introuvable", "registrant.alreadyUnregistered": "Déjà non inscrit à l'événement", "translation.alreadyPresent": "Traduction déjà présente", "translation.notFound": "Traduction introuvable", - "parameter.missing": "Paramètre de saut manquant. Réglez-le sur 0 ou sur une autre valeur" + "parameter.missing": "Paramètre de saut manquant. Réglez-le sur 0 ou sur une autre valeur", + "tag.alreadyExists": "Un tag avec le même nom existe déjà à ce niveau", + "invalid.contentType": "Type de contenu invalide. multipart/form-data attendu.", + "invalid.fieldFileName": "Nom de champ de fichier non valide reçu.", + "file.sizeExceeded": "La taille du fichier dépasse la limite autorisée.", + "file.notFound": "Fichier non trouvé.", + "invalid.argument": "Argument non valide reçu." } diff --git a/locales/hi.json b/locales/hi.json index 74d3372fb0..366c04895f 100644 --- a/locales/hi.json +++ b/locales/hi.json @@ -29,10 +29,17 @@ "invalid.fileType": "अमान्य फ़ाइल प्रकार", "invalid.refreshToken": "अमान्य रीफ़्रेश टोकन", "invalid.credentials": "अवैध प्रत्यय पत्र", + "invalid.timeoutRange": "अमान्य टाइमआउट रेंज", "registrant.alreadyExist": "घटना के लिए पहले से पंजीकृत", "member.notFound": "सदस्य अनुपस्थित", "registrant.alreadyUnregistered": "घटना के लिए पहले से ही अपंजीकृत", "translation.alreadyPresent": "अनुवाद पहले से मौजूद है", "translation.notFound": "अनुवाद नहीं मिला", - "parameter.missing": "छोड़ें पैरामीटर मौजूद नहीं है. इसे 0 या किसी अन्य मान पर सेट करें" + "parameter.missing": "छोड़ें पैरामीटर मौजूद नहीं है. इसे 0 या किसी अन्य मान पर सेट करें", + "tag.alreadyExists": "इस स्तर पर समान नाम वाला टैग पहले से मौजूद है", + "invalid.contentType": "अमान्य सामग्री प्रकार। अपेक्षित है multipart/form-data।", + "invalid.fieldFileName": "अमान्य फ़ाइल इनपुट फ़ील्ड नाम प्राप्त हुआ।", + "file.sizeExceeded": "फ़ाइल का आकार अनुमत सीमा से अधिक है।", + "file.notFound": "फ़ाइल नहीं मिली।", + "invalid.argument": "अमान्य तर्क प्राप्त हुआ।" } diff --git a/locales/sp.json b/locales/sp.json index cec263813a..59a5fdc801 100644 --- a/locales/sp.json +++ b/locales/sp.json @@ -28,10 +28,17 @@ "invalid.fileType": "Tipo de archivo no válido", "invalid.refreshToken": "Token de actualización no válido", "invalid.credentials": "Credenciales no válidas", + "invalid.timeoutRange": "Rango de tiempo de espera no válido", "registrant.alreadyExist": "Ya inscrito para el evento", "member.notFound": "Miembro no encontrado", "registrant.alreadyUnregistered": "Ya no está registrado para el evento", "translation.alreadyPresent": "Traducción ya presente", "translation.notFound": "Traducción no encontrada", - "parameter.missing": "Falta el parámetro Omitir. Establézcalo en 0 o en algún otro valor" + "parameter.missing": "Falta el parámetro Omitir. Establézcalo en 0 o en algún otro valor", + "tag.alreadyExists": "Ya existe una etiqueta con el mismo nombre en este nivel", + "invalid.contentType": "Tipo de contenido no válido. Se esperaba multipart/form-data.", + "invalid.fieldFileName": "Se recibió un nombre de campo de archivo no válido.", + "file.sizeExceeded": "El tamaño del archivo supera el límite permitido.", + "file.notFound": "Archivo no encontrado.", + "invalid.argument": "Se recibió un argumento no válido." } diff --git a/locales/zh.json b/locales/zh.json index 16453c5236..7593b1eb2a 100644 --- a/locales/zh.json +++ b/locales/zh.json @@ -28,10 +28,17 @@ "invalid.fileType": "無效的文件類型", "invalid.refreshToken": "無效的刷新令牌", "invalid.credentials": "無效的憑據", + "invalid.timeoutRange": "无效的超时范围", "registrant.alreadyExist": "已经报名参加活动", "member.notFound": "未找到成员", "registrant.alreadyUnregistered": "已取消注册该活动", "translation.alreadyPresent": "翻译已经存在", "translation.notFound": "找不到翻译", - "parameter.missing": "缺少跳过参数。将其设置为 0 或其他值" + "parameter.missing": "缺少跳过参数。将其设置为 0 或其他值", + "tag.alreadyExists": "此级别已存在相同名称的标签", + "invalid.contentType": "内容类型无效。预期为 multipart/form-data。", + "invalid.fieldFileName": "收到无效的文件输入字段名称。", + "file.sizeExceeded": "文件大小超过允许的限制。", + "file.notFound": "文件未找到。", + "invalid.argument": "收到无效的参数。" } diff --git a/package-lock.json b/package-lock.json index 350f57f1c0..b0b8729f1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,38 +9,39 @@ "version": "1.0.0", "license": "GNU General Public License v3.0", "dependencies": { - "@apollo/server": "^4.11.0", + "@apollo/server": "^4.11.2", + "@aws-sdk/client-s3": "^3.675.0", "@faker-js/faker": "^9.0.1", "@graphql-inspector/cli": "^5.0.6", - "@graphql-tools/resolvers-composition": "^7.0.1", + "@graphql-tools/resolvers-composition": "^7.0.2", "@graphql-tools/schema": "^10.0.6", "@graphql-tools/utils": "^10.3.2", "@parcel/watcher": "^2.4.1", "@types/graphql-upload": "^16.0.5", "@types/yargs": "^17.0.33", "@typescript-eslint/eslint-plugin": "^8.2.0", - "@typescript-eslint/parser": "^8.0.1", - "axios": "^1.7.4", + "@typescript-eslint/parser": "^8.11.0", + "axios": "^1.7.7", "bcryptjs": "^2.4.3", "bluebird": "3.7.2", "cls-hooked": "^4.2.2", "copy-paste": "^1.5.3", "cors": "^2.8.5", "cross-env": "^7.0.3", - "date-fns": "^3.3.1", + "date-fns": "^4.1.0", "dotenv": "^16.4.1", "express": "^4.19.2", "express-mongo-sanitize": "^2.2.0", - "express-rate-limit": "^7.4.0", + "express-rate-limit": "^7.4.1", "graphql": "^16.9.0", "graphql-depth-limit": "^1.1.0", "graphql-scalars": "^1.20.1", "graphql-subscriptions": "^2.0.0", "graphql-tag": "^2.12.6", - "graphql-upload": "^16.0.2", - "graphql-voyager": "^2.0.0", + "graphql-upload": "^17.0.0", + "graphql-voyager": "^2.1.0", "graphql-ws": "^5.16.0", - "helmet": "^7.1.0", + "helmet": "^8.0.0", "i18n": "^0.15.1", "image-hash": "^5.3.1", "ioredis": "^5.4.1", @@ -52,59 +53,67 @@ "mongoose": "^8.3.2", "mongoose-paginate-v2": "^1.8.3", "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", "nanoid": "^5.0.7", - "nodemailer": "^6.9.15", + "nodemailer": "^6.9.16", "pm2": "^5.4.0", "redis": "^4.7.0", "rrule": "^2.8.1", "typedoc-plugin-markdown": "^4.2.7", - "uuid": "^10.0.0", + "uuid": "^11.0.1", "validator": "^13.12.0", - "winston": "^3.14.2", + "winston": "^3.15.0", "ws": "^8.18.0", "yargs": "^17.7.2", "zod": "^3.23.8", "zod-error": "^1.5.0" }, "devDependencies": { - "@graphql-codegen/cli": "^5.0.2", - "@graphql-codegen/typescript": "^4.0.9", + "@eslint/compat": "^1.1.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "^8.57.0", + "@graphql-codegen/cli": "^5.0.3", + "@graphql-codegen/typescript": "^4.1.0", "@graphql-codegen/typescript-resolvers": "^4.2.1", "@graphql-eslint/eslint-plugin": "^3.20.1", "@parcel/watcher": "^2.4.1", "@types/bcryptjs": "^2.4.6", - "@types/cls-hooked": "^4.3.8", + "@types/cls-hooked": "^4.3.9", "@types/copy-paste": "^1.1.30", "@types/cors": "^2.8.17", "@types/express": "^4.17.17", - "@types/express-rate-limit": "^6.0.0", + "@types/express-rate-limit": "^6.0.2", "@types/graphql-depth-limit": "^1.1.6", "@types/i18n": "^0.13.12", "@types/inquirer": "^9.0.7", "@types/jsonwebtoken": "^9.0.7", - "@types/lodash": "^4.17.7", + "@types/lodash": "^4.17.13", "@types/mongoose-paginate-v2": "^1.6.5", "@types/morgan": "^1.9.9", - "@types/node": "^22.5.4", - "@types/nodemailer": "^6.4.15", + "@types/multer": "^1.4.12", + "@types/node": "^22.9.0", + "@types/nodemailer": "^6.4.16", + "@types/supertest": "^6.0.2", "@types/uuid": "^10.0.0", - "@types/validator": "^13.12.0", - "@vitest/coverage-v8": "^2.1.1", + "@types/validator": "^13.12.2", + "@vitest/coverage-v8": "^2.1.3", "cls-bluebird": "^2.1.0", - "concurrently": "^9.0.0", - "eslint": "^8.56.0", + "concurrently": "^9.0.1", + "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-tsdoc": "^0.3.0", "get-graphql-schema": "^2.1.2", - "graphql-markdown": "^7.1.0", - "husky": "^9.1.5", + "globals": "^15.12.0", + "graphql-markdown": "^7.3.0", + "husky": "^9.1.6", "lint-staged": "^15.2.10", "prettier": "^3.3.3", "rimraf": "^6.0.1", + "supertest": "^7.0.0", "tsx": "^4.19.1", "typescript": "^5.5.4", - "vitest": "^2.0.5" + "vitest": "^2.1.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -160,9 +169,9 @@ } }, "node_modules/@apollo/server": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.0.tgz", - "integrity": "sha512-SWDvbbs0wl2zYhKG6aGLxwTJ72xpqp0awb2lotNpfezd9VcAvzaUizzKQqocephin2uMoaA8MguoyBmgtPzNWw==", + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.2.tgz", + "integrity": "sha512-WUTHY7DDek8xAMn4Woa9Bl8duQUDzRYQkosX/d1DtCsBWESZyApR7ndnI5d6+W4KSTtqBHhJFkusEI7CWuIJXg==", "dependencies": { "@apollo/cache-control-types": "^1.0.3", "@apollo/server-gateway-interface": "^1.1.1", @@ -180,7 +189,7 @@ "@types/node-fetch": "^2.6.1", "async-retry": "^1.2.1", "cors": "^2.8.5", - "express": "^4.17.1", + "express": "^4.21.1", "loglevel": "^1.6.8", "lru-cache": "^7.10.1", "negotiator": "^0.6.3", @@ -547,1829 +556,2857 @@ "node": ">=14" } }, - "node_modules/@babel/code-frame": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", - "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", "dependencies": { - "@babel/highlight": "^7.24.6", - "picocolors": "^1.0.0" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", - "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", - "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/core": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz", - "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-compilation-targets": "^7.24.6", - "@babel/helper-module-transforms": "^7.24.6", - "@babel/helpers": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/template": "^7.24.6", - "@babel/traverse": "^7.24.6", - "@babel/types": "^7.24.6", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } }, - "node_modules/@babel/generator": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", - "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dependencies": { - "@babel/types": "^7.24.6", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", - "dev": true, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dependencies": { - "@babel/types": "^7.22.5" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", - "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dependencies": { - "@babel/compat-data": "^7.24.6", - "@babel/helper-validator-option": "^7.24.6", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", - "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", - "dev": true, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", - "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", - "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", - "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "dependencies": { - "@babel/types": "^7.24.6" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", - "dev": true, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", "dependencies": { - "@babel/types": "^7.23.0" + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", - "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dependencies": { - "@babel/types": "^7.24.6" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", - "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-module-imports": "^7.24.6", - "@babel/helper-simple-access": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/helper-validator-identifier": "^7.24.6" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" + "node_modules/@aws-sdk/client-s3": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.675.0.tgz", + "integrity": "sha512-WKPc9fwFsD0SrWmrj0MdMHE+hQ0YAIGLqACmTnL1yW76qAwjIlFa9TAhR8f29aVCQodt/I6HDf9dHX/F+GyDFg==", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.675.0", + "@aws-sdk/client-sts": "3.675.0", + "@aws-sdk/core": "3.667.0", + "@aws-sdk/credential-provider-node": "3.675.0", + "@aws-sdk/middleware-bucket-endpoint": "3.667.0", + "@aws-sdk/middleware-expect-continue": "3.667.0", + "@aws-sdk/middleware-flexible-checksums": "3.669.0", + "@aws-sdk/middleware-host-header": "3.667.0", + "@aws-sdk/middleware-location-constraint": "3.667.0", + "@aws-sdk/middleware-logger": "3.667.0", + "@aws-sdk/middleware-recursion-detection": "3.667.0", + "@aws-sdk/middleware-sdk-s3": "3.674.0", + "@aws-sdk/middleware-ssec": "3.667.0", + "@aws-sdk/middleware-user-agent": "3.669.0", + "@aws-sdk/region-config-resolver": "3.667.0", + "@aws-sdk/signature-v4-multi-region": "3.674.0", + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-endpoints": "3.667.0", + "@aws-sdk/util-user-agent-browser": "3.675.0", + "@aws-sdk/util-user-agent-node": "3.669.0", + "@aws-sdk/xml-builder": "3.662.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/eventstream-serde-browser": "^3.0.10", + "@smithy/eventstream-serde-config-resolver": "^3.0.7", + "@smithy/eventstream-serde-node": "^3.0.9", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-blob-browser": "^3.1.6", + "@smithy/hash-node": "^3.0.7", + "@smithy/hash-stream-node": "^3.1.6", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/md5-js": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-stream": "^3.1.9", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.1.6", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "node_modules/@aws-sdk/client-sso": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.675.0.tgz", + "integrity": "sha512-2goBCEr4acZJ1YJ69eWPTsIfZUbO7enog+lBA5kZShDiwovqzwYSHSlf6OGz4ETs2xT1n7n+QfKY0p+TluTfEw==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.667.0", + "@aws-sdk/middleware-host-header": "3.667.0", + "@aws-sdk/middleware-logger": "3.667.0", + "@aws-sdk/middleware-recursion-detection": "3.667.0", + "@aws-sdk/middleware-user-agent": "3.669.0", + "@aws-sdk/region-config-resolver": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-endpoints": "3.667.0", + "@aws-sdk/util-user-agent-browser": "3.675.0", + "@aws-sdk/util-user-agent-node": "3.669.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", - "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5" + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.675.0.tgz", + "integrity": "sha512-4kEcaa2P/BFz+xy5tagbtzM08gbjHXyYqW+n6SJuUFK7N6bZNnA4cu1hVgHcqOqk8Dbwv7fiseGT0x3Hhqjwqg==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.667.0", + "@aws-sdk/credential-provider-node": "3.675.0", + "@aws-sdk/middleware-host-header": "3.667.0", + "@aws-sdk/middleware-logger": "3.667.0", + "@aws-sdk/middleware-recursion-detection": "3.667.0", + "@aws-sdk/middleware-user-agent": "3.669.0", + "@aws-sdk/region-config-resolver": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-endpoints": "3.667.0", + "@aws-sdk/util-user-agent-browser": "3.675.0", + "@aws-sdk/util-user-agent-node": "3.669.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", - "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", - "dependencies": { - "@babel/types": "^7.24.6" + "@aws-sdk/client-sts": "^3.675.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.675.0.tgz", + "integrity": "sha512-zgjyR4GyuONeDGJBKNt9lFJ8HfDX7rpxZZVR7LSXr9lUkjf6vUGgD2k/K4UAoOTWCKKCor6TA562ezGlA8su6Q==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.675.0", + "@aws-sdk/core": "3.667.0", + "@aws-sdk/credential-provider-node": "3.675.0", + "@aws-sdk/middleware-host-header": "3.667.0", + "@aws-sdk/middleware-logger": "3.667.0", + "@aws-sdk/middleware-recursion-detection": "3.667.0", + "@aws-sdk/middleware-user-agent": "3.669.0", + "@aws-sdk/region-config-resolver": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-endpoints": "3.667.0", + "@aws-sdk/util-user-agent-browser": "3.675.0", + "@aws-sdk/util-user-agent-node": "3.669.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" + "node_modules/@aws-sdk/core": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.667.0.tgz", + "integrity": "sha512-pMcDVI7Tmdsc8R3sDv0Omj/4iRParGY+uJtAfF669WnZfDfaBQaix2Mq7+Mu08vdjqO9K3gicFvjk9S1VLmOKA==", + "dependencies": { + "@aws-sdk/types": "3.667.0", + "@smithy/core": "^2.4.8", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/property-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/signature-v4": "^4.2.0", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-middleware": "^3.0.7", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", - "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.667.0.tgz", + "integrity": "sha512-zZbrkkaPc54WXm+QAnpuv0LPNfsts0HPPd+oCECGs7IQRaFsGj187cwvPg9RMWDFZqpm64MdBDoA8OQHsqzYCw==", "dependencies": { - "@babel/types": "^7.24.6" + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", - "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.667.0.tgz", + "integrity": "sha512-sjtybFfERZWiqTY7fswBxKQLvUkiCucOWyqh3IaPo/4nE1PXRnaZCVG0+kRBPrYIxWqiVwytvZzMJy8sVZcG0A==", + "dependencies": { + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-stream": "^3.1.9", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", - "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.675.0.tgz", + "integrity": "sha512-kCBlC6grpbpCvgowk9T4JHZxJ88VfN0r77bDZClcadFRAKQ8UHyO02zhgFCfUdnU1lNv1mr3ngEcGN7XzJlYWA==", + "dependencies": { + "@aws-sdk/core": "3.667.0", + "@aws-sdk/credential-provider-env": "3.667.0", + "@aws-sdk/credential-provider-http": "3.667.0", + "@aws-sdk/credential-provider-process": "3.667.0", + "@aws-sdk/credential-provider-sso": "3.675.0", + "@aws-sdk/credential-provider-web-identity": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", - "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.675.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.675.0.tgz", + "integrity": "sha512-VO1WVZCDmAYu4sY/6qIBzdm5vJTxLhWKJWvL5kVFfSe8WiNNoHlTqYYUK9vAm/JYpIgFLTefPbIc5W4MK7o6Pg==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.667.0", + "@aws-sdk/credential-provider-http": "3.667.0", + "@aws-sdk/credential-provider-ini": "3.675.0", + "@aws-sdk/credential-provider-process": "3.667.0", + "@aws-sdk/credential-provider-sso": "3.675.0", + "@aws-sdk/credential-provider-web-identity": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/helpers": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", - "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.667.0.tgz", + "integrity": "sha512-HZHnvop32fKgsNHkdhVaul7UzQ25sEc0j9yqA4bjhtbk0ECl42kj3f1pJ+ZU/YD9ut8lMJs/vVqiOdNThVdeBw==", "dependencies": { - "@babel/template": "^7.24.6", - "@babel/types": "^7.24.6" + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/highlight": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", - "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.675.0.tgz", + "integrity": "sha512-p/EE2c0ebSgRhg1Fe1OH2+xNl7j1P4DTc7kZy1mX1NJ72fkqnGgBuf1vk5J9RmiRpbauPNMlm+xohjkGS7iodA==", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.6", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@aws-sdk/client-sso": "3.675.0", + "@aws-sdk/core": "3.667.0", + "@aws-sdk/token-providers": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.667.0.tgz", + "integrity": "sha512-t8CFlZMD/1p/8Cli3rvRiTJpjr/8BO64gw166AHgFZYSN2h95L2l1tcW0jpsc3PprA32nLg1iQVKYt4WGM4ugw==", "dependencies": { - "color-convert": "^1.9.0" + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=4" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.667.0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.667.0.tgz", + "integrity": "sha512-XGz4jMAkDoTyFdtLz7ZF+C05IAhCTC1PllpvTBaj821z/L0ilhbqVhrT/f2Buw8Id/K5A390csGXgusXyrFFjA==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=4" + "node": ">=16.0.0" } }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.667.0.tgz", + "integrity": "sha512-0TiSL9S5DSG95NHGIz6qTMuV7GDKVn8tvvGSrSSZu/wXO3JaYSH0AElVpYfc4PtPRqVpEyNA7nnc7W56mMCLWQ==", "dependencies": { - "color-name": "1.1.3" + "@aws-sdk/types": "3.667.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.669.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.669.0.tgz", + "integrity": "sha512-01UQLoUzVwWMf+b+AEuwJ2lluBD+Cp8AcbyEHqvEaPdjGKHIS4BCvnY70mZYnAfRtL8R2h9tt7iI61oWU3Gjkg==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=0.8.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.667.0.tgz", + "integrity": "sha512-Z7fIAMQnPegs7JjAQvlOeWXwpMRfegh5eCoIP6VLJIeR6DLfYKbP35JBtt98R6DXslrN2RsbTogjbxPEDQfw1w==", + "dependencies": { + "@aws-sdk/types": "3.667.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=4" + "node": ">=16.0.0" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.667.0.tgz", + "integrity": "sha512-ob85H3HhT3/u5O+x0o557xGZ78vSNeSSwMaSitxdsfs2hOuoUl1uk+OeLpi1hkuJnL41FPpokV7TVII2XrFfmg==", "dependencies": { - "has-flag": "^3.0.0" + "@aws-sdk/types": "3.667.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=4" + "node": ">=16.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", - "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", - "bin": { - "parser": "bin/babel-parser.js" + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.667.0.tgz", + "integrity": "sha512-PtTRNpNm/5c746jRgZCNg4X9xEJIwggkGJrF0GP9AB1ANg4pc/sF2Fvn1NtqPe9wtQ2stunJprnm5WkCHN7QiA==", + "dependencies": { + "@aws-sdk/types": "3.667.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.667.0.tgz", + "integrity": "sha512-U5glWD3ehFohzpUpopLtmqAlDurGWo2wRGPNgi4SwhWU7UDt6LS7E/UvJjqC0CUrjlzOw+my2A+Ncf+fisMhxQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "@aws-sdk/types": "3.667.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.674.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.674.0.tgz", + "integrity": "sha512-IvXnWrKy4mO+I44kLYHd6Wlw+FdB4sg1jvHCmnZo1KNaAFIA3x1iXgOaZynKoBdEmol3xfr2uDbeXUQvIwoIgg==", + "dependencies": { + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/core": "^2.4.8", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/signature-v4": "^4.2.0", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-stream": "^3.1.9", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "dev": true, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.667.0.tgz", + "integrity": "sha512-1wuAUZIkmZIvOmGg5qNQU821CGFHhkuKioxXgNh0DpUxZ9+AeiV7yorJr+bqkb2KBFv1i1TnzGRecvKf/KvZIQ==", "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" + "@aws-sdk/types": "3.667.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.669.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.669.0.tgz", + "integrity": "sha512-K8ScPi45zjJrj5Y2gRqVsvKKQCQbvQBfYGcBw9ZOx9TTavH80bOCBjWg/GFnvs4f37tqVc1wMN2oGvcTF6HveQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@aws-sdk/core": "3.667.0", + "@aws-sdk/types": "3.667.0", + "@aws-sdk/util-endpoints": "3.667.0", + "@smithy/core": "^2.4.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", - "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", - "dev": true, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.667.0.tgz", + "integrity": "sha512-iNr+JhhA902JMKHG9IwT9YdaEx6KGl6vjAL5BRNeOjfj4cZYMog6Lz/IlfOAltMtT0w88DAHDEFrBd2uO0l2eg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@aws-sdk/types": "3.667.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.7", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", - "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.674.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.674.0.tgz", + "integrity": "sha512-VMQWbtcbg4FV/fILrODADV21pPg9AghuEzQlW2kH0hCtacvBwFl7eBxIiCBLLtkNple+CVPJvyBcqOZdBkEv/w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@aws-sdk/middleware-sdk-s3": "3.674.0", + "@aws-sdk/types": "3.667.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/signature-v4": "^4.2.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", - "dev": true, + "node_modules/@aws-sdk/token-providers": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.667.0.tgz", + "integrity": "sha512-ZecJlG8p6D4UTYlBHwOWX6nknVtw/OBJ3yPXTSajBjhUlj9lE2xvejI8gl4rqkyLXk7z3bki+KR4tATbMaM9yg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@aws-sdk/types": "3.667.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-sdk/client-sso-oidc": "^3.667.0" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, + "node_modules/@aws-sdk/types": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.667.0.tgz", + "integrity": "sha512-gYq0xCsqFfQaSL/yT1Gl1vIUjtsg7d7RhnUfsXaHt8xTxOKRTdH9GjbesBjXOzgOvB0W0vfssfreSNGFlOOMJg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", - "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", - "dev": true, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", - "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", - "dev": true, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.667.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.667.0.tgz", + "integrity": "sha512-X22SYDAuQJWnkF1/q17pkX3nGw5XMD9YEUbmt87vUnRq7iyJ3JOpl6UKOBeUBaL838wA5yzdbinmCITJ/VZ1QA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@aws-sdk/types": "3.667.0", + "@smithy/types": "^3.5.0", + "@smithy/util-endpoints": "^2.1.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "dependencies": { + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz", - "integrity": "sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw==", - "dev": true, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.675.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.675.0.tgz", + "integrity": "sha512-HW4vGfRiX54RLcsYjLuAhcBBJ6lRVEZd7njfGpAwBB9s7BH8t48vrpYbyA5XbbqbTvXfYBnugQCUw9HWjEa1ww==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@aws-sdk/types": "3.667.0", + "@smithy/types": "^3.5.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.669.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.669.0.tgz", + "integrity": "sha512-9jxCYrgggy2xd44ZASqI7AMiRVaSiFp+06Kg8BQSU0ijKpBJlwcsqIS8pDT/n6LxuOw2eV5ipvM2C0r1iKzrGA==", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.669.0", + "@aws-sdk/types": "3.667.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", - "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", - "dev": true, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.662.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.662.0.tgz", + "integrity": "sha512-ikLkXn0igUpnJu2mCZjklvmcDGWT9OaLRv3JyC/cRkTaaSrblPjPM7KKsltxdMTLQ+v7fjCN0TsJpxphMfaOPA==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", - "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", - "dev": true, + "node_modules/@babel/code-frame": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/template": "^7.24.0" + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", - "dev": true, + "node_modules/@babel/compat-data": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", + "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz", + "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helpers": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/traverse": "^7.24.6", + "@babel/types": "^7.24.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz", - "integrity": "sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==", - "dev": true, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@babel/generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", + "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-flow": "^7.24.1" + "@babel/types": "^7.24.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", - "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", - "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", - "dev": true, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", + "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/compat-data": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-literals": { + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", - "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz", + "integrity": "sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", - "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", - "dev": true, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", + "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", + "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", - "dev": true, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", + "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" + "@babel/types": "^7.24.6" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", - "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", - "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", - "dev": true, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", + "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/types": "^7.24.6" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", - "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", - "dev": true, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", + "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", - "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", - "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.23.3", - "@babel/types": "^7.23.4" - }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { + "node_modules/@babel/helper-replace-supers": { "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", - "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", + "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.23.0", + "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", - "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", - "dev": true, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", + "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/types": "^7.24.6" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", - "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", - "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", "dependencies": { - "regenerator-runtime": "^0.14.0" + "@babel/types": "^7.24.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/template": { + "node_modules/@babel/helper-string-parser": { "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", - "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", - "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6" - }, + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", + "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse": { + "node_modules/@babel/helper-validator-identifier": { "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", - "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", + "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", + "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", "dependencies": { - "@babel/code-frame": "^7.24.6", - "@babel/generator": "^7.24.6", - "@babel/helper-environment-visitor": "^7.24.6", - "@babel/helper-function-name": "^7.24.6", - "@babel/helper-hoist-variables": "^7.24.6", - "@babel/helper-split-export-declaration": "^7.24.6", - "@babel/parser": "^7.24.6", - "@babel/types": "^7.24.6", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/types": { + "node_modules/@babel/highlight": { "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", - "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", "dependencies": { - "@babel/helper-string-parser": "^7.24.6", "@babel/helper-validator-identifier": "^7.24.6", - "to-fast-properties": "^2.0.0" + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@canvas/image-data": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.0.0.tgz", - "integrity": "sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==" - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "optional": true, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { - "node": ">=0.1.90" + "node": ">=4" } }, - "node_modules/@cwasm/webp": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@cwasm/webp/-/webp-0.1.5.tgz", - "integrity": "sha512-ceIZQkyxK+s7mmItNcWqqHdOBiJAxYxTnrnPNgUNjldB1M9j+Bp/3eVIVwC8rUFyN/zoFwuT0331pyY3ackaNA==", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "@canvas/image-data": "^1.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "color-name": "1.1.3" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, - "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "stylis": "4.2.0" + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "@emotion/memoize": "^0.8.1" + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "node_modules/@babel/parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", + "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@emotion/react": { - "version": "11.10.5", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.5.tgz", - "integrity": "sha512-TZs6235tCJ/7iF6/rvTaOH4oxQg2gMAcdHemjwLKIjKz4rRuYe1HJ2TQJKnAcRAfOUDdU8XoDadCe1rl72iv8A==", + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.10.5", - "@emotion/cache": "^11.10.5", - "@emotion/serialize": "^1.1.1", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "hoist-non-react-statics": "^3.3.1" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "react": ">=16.8.0" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@types/react": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/serialize": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", - "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", + "dev": true, "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" - }, - "node_modules/@emotion/styled": { - "version": "11.10.5", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.5.tgz", - "integrity": "sha512-8EP6dD7dMkdku2foLoruPCNkRevzdcBaY6q0l0OsbyJK+x8D9HWjX27ARiSIKNF634hY9Zdoedh8bJCiva8yZw==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.10.5", - "@emotion/is-prop-valid": "^1.2.0", - "@emotion/serialize": "^1.1.1", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@emotion/utils": "^1.2.0" + "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { - "@babel/core": "^7.0.0", - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz", + "integrity": "sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "react": ">=16.8.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" - }, - "node_modules/@envelop/core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@envelop/core/-/core-5.0.1.tgz", - "integrity": "sha512-wxA8EyE1fPnlbP0nC/SFI7uU8wSNf4YjxZhAPu0P63QbgIvqHtHsH4L3/u+rsTruzhk3OvNRgQyLsMfaR9uzAQ==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", + "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", "dependencies": { - "@envelop/types": "5.0.0", - "tslib": "^2.5.0" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@envelop/types": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@envelop/types/-/types-5.0.0.tgz", - "integrity": "sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", + "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", + "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz", + "integrity": "sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", + "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=18" + "node": ">=4" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", + "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/template": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", + "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz", + "integrity": "sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/plugin-syntax-flow": "^7.24.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", + "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", + "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", + "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", + "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-simple-access": "^7.22.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", + "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-replace-supers": "^7.24.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", + "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", + "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz", + "integrity": "sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz", + "integrity": "sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==", "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/types": "^7.23.4" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", + "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", + "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", + "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "node_modules/@babel/runtime": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz", + "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@babel/template": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", + "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@babel/code-frame": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/traverse": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", + "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dependencies": { - "type-fest": "^0.20.2" - }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", + "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/helper-string-parser": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6", + "to-fast-properties": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@canvas/image-data": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.0.0.tgz", + "integrity": "sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==" + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "optional": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.1.90" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node_modules/@cwasm/webp": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@cwasm/webp/-/webp-0.1.5.tgz", + "integrity": "sha512-ceIZQkyxK+s7mmItNcWqqHdOBiJAxYxTnrnPNgUNjldB1M9j+Bp/3eVIVwC8rUFyN/zoFwuT0331pyY3ackaNA==", + "dependencies": { + "@canvas/image-data": "^1.0.0" } }, - "node_modules/@faker-js/faker": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.1.tgz", - "integrity": "sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/fakerjs" - } - ], - "engines": { - "node": ">=18.0.0", - "npm": ">=9.0.0" + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, - "node_modules/@graphql-codegen/add": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.2.tgz", - "integrity": "sha512-ouBkSvMFUhda5VoKumo/ZvsZM9P5ZTyDsI8LW18VxSNWOjrTeLXBWHG8Gfaai0HwhflPtCYVABbriEcOmrRShQ==", - "dev": true, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@graphql-codegen/cli": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.2.tgz", - "integrity": "sha512-MBIaFqDiLKuO4ojN6xxG9/xL9wmfD3ZjZ7RsPjwQnSHBCUXnEkdKvX+JVpx87Pq29Ycn8wTJUguXnTZ7Di0Mlw==", - "dev": true, + "node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", "dependencies": { - "@babel/generator": "^7.18.13", - "@babel/template": "^7.18.10", - "@babel/types": "^7.18.13", - "@graphql-codegen/client-preset": "^4.2.2", - "@graphql-codegen/core": "^4.0.2", - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-tools/apollo-engine-loader": "^8.0.0", - "@graphql-tools/code-file-loader": "^8.0.0", - "@graphql-tools/git-loader": "^8.0.0", - "@graphql-tools/github-loader": "^8.0.0", - "@graphql-tools/graphql-file-loader": "^8.0.0", - "@graphql-tools/json-file-loader": "^8.0.0", - "@graphql-tools/load": "^8.0.0", - "@graphql-tools/prisma-loader": "^8.0.0", - "@graphql-tools/url-loader": "^8.0.0", - "@graphql-tools/utils": "^10.0.0", - "@whatwg-node/fetch": "^0.8.0", - "chalk": "^4.1.0", - "cosmiconfig": "^8.1.3", - "debounce": "^1.2.0", - "detect-indent": "^6.0.0", - "graphql-config": "^5.0.2", - "inquirer": "^8.0.0", - "is-glob": "^4.0.1", - "jiti": "^1.17.1", - "json-to-pretty-yaml": "^1.2.2", - "listr2": "^4.0.5", - "log-symbols": "^4.0.0", - "micromatch": "^4.0.5", - "shell-quote": "^1.7.3", - "string-env-interpolation": "^1.0.1", - "ts-log": "^2.2.3", - "tslib": "^2.4.0", - "yaml": "^2.3.1", - "yargs": "^17.0.0" - }, - "bin": { - "gql-gen": "cjs/bin.js", - "graphql-code-generator": "cjs/bin.js", - "graphql-codegen": "cjs/bin.js", - "graphql-codegen-esm": "esm/bin.js" + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "node_modules/@emotion/react": { + "version": "11.13.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz", + "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { - "@parcel/watcher": "^2.1.0", - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "react": ">=16.8.0" }, "peerDependenciesMeta": { - "@parcel/watcher": { + "@types/react": { "optional": true } } }, - "node_modules/@graphql-codegen/client-preset": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.2.4.tgz", - "integrity": "sha512-k1c8v2YxJhhITGQGxViG9asLAoop9m7X9duU7Zztqjc98ooxsUzXICfvAWsH3mLAUibXAx4Ax6BPzKsTtQmBPg==", - "dev": true, + "node_modules/@emotion/serialize": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz", + "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7", - "@graphql-codegen/add": "^5.0.2", - "@graphql-codegen/gql-tag-operations": "4.0.6", - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-codegen/typed-document-node": "^5.0.6", - "@graphql-codegen/typescript": "^4.0.6", - "@graphql-codegen/typescript-operations": "^4.2.0", - "@graphql-codegen/visitor-plugin-common": "^5.1.0", - "@graphql-tools/documents": "^1.0.0", - "@graphql-tools/utils": "^10.0.0", - "@graphql-typed-document-node/core": "3.2.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.1", + "csstype": "^3.0.2" } }, - "node_modules/@graphql-codegen/core": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz", - "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" }, - "node_modules/@graphql-codegen/gql-tag-operations": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.6.tgz", - "integrity": "sha512-y6iXEDpDNjwNxJw3WZqX1/Znj0QHW7+y8O+t2V8qvbTT+3kb2lr9ntc8By7vCr6ctw9tXI4XKaJgpTstJDOwFA==", - "dev": true, + "node_modules/@emotion/styled": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-codegen/visitor-plugin-common": "5.1.0", - "@graphql-tools/utils": "^10.0.0", - "auto-bind": "~4.0.0", - "tslib": "~2.6.0" + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" }, "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@graphql-codegen/plugin-helpers": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.4.tgz", - "integrity": "sha512-MOIuHFNWUnFnqVmiXtrI+4UziMTYrcquljaI5f/T/Bc7oO7sXcfkAvgkNWEEi9xWreYwvuer3VHCuPI/lAFWbw==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.0", - "change-case-all": "1.0.15", - "common-tags": "1.8.2", - "import-from": "4.0.0", - "lodash": "~4.17.0", - "tslib": "~2.6.0" - }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "react": ">=16.8.0" } }, - "node_modules/@graphql-codegen/schema-ast": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.0.2.tgz", - "integrity": "sha512-5mVAOQQK3Oz7EtMl/l3vOQdc2aYClUzVDHHkMvZlunc+KlGgl81j8TLa+X7ANIllqU4fUEsQU3lJmk4hXP6K7Q==", - "dev": true, + "node_modules/@emotion/utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz", + "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + }, + "node_modules/@envelop/core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@envelop/core/-/core-5.0.1.tgz", + "integrity": "sha512-wxA8EyE1fPnlbP0nC/SFI7uU8wSNf4YjxZhAPu0P63QbgIvqHtHsH4L3/u+rsTruzhk3OvNRgQyLsMfaR9uzAQ==", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-tools/utils": "^10.0.0", - "tslib": "~2.6.0" + "@envelop/types": "5.0.0", + "tslib": "^2.5.0" }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@graphql-codegen/typed-document-node": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.6.tgz", - "integrity": "sha512-US0J95hOE2/W/h42w4oiY+DFKG7IetEN1mQMgXXeat1w6FAR5PlIz4JrRrEkiVfVetZ1g7K78SOwBD8/IJnDiA==", - "dev": true, + "node_modules/@envelop/types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@envelop/types/-/types-5.0.0.tgz", + "integrity": "sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-codegen/visitor-plugin-common": "5.1.0", - "auto-bind": "~4.0.0", - "change-case-all": "1.0.15", - "tslib": "~2.6.0" + "tslib": "^2.5.0" }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@graphql-codegen/typescript": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.0.9.tgz", - "integrity": "sha512-0O35DMR4d/ctuHL1Zo6mRUUzp0BoszKfeWsa6sCm/g70+S98+hEfTwZNDkQHylLxapiyjssF9uw/F+sXqejqLw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/schema-ast": "^4.0.2", - "@graphql-codegen/visitor-plugin-common": "5.3.1", - "auto-bind": "~4.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@graphql-codegen/typescript-operations": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.2.0.tgz", - "integrity": "sha512-lmuwYb03XC7LNRS8oo9M4/vlOrq/wOKmTLBHlltK2YJ1BO/4K/Q9Jdv/jDmJpNydHVR1fmeF4wAfsIp1f9JibA==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-codegen/typescript": "^4.0.6", - "@graphql-codegen/visitor-plugin-common": "5.1.0", - "auto-bind": "~4.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@graphql-codegen/typescript-resolvers": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-4.2.1.tgz", - "integrity": "sha512-q/ggqNSKNGG9bn49DdZrw2KokagDZmzl1EpxIfzmpHrPa3XaCLfxQuNNEUhqEXtJzQZtLfuYvGy1y+MrTU8WnA==", - "dev": true, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", + "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", + "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", + "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@faker-js/faker": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.0.1.tgz", + "integrity": "sha512-4mDeYIgM3By7X6t5E6eYwLAa+2h4DeZDF7thhzIg6XB76jeEvMwadYAMCFJL/R4AnEBcAUO9+gL0vhy3s+qvZA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": ">=18.0.0", + "npm": ">=9.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" + }, + "node_modules/@graphql-codegen/add": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz", + "integrity": "sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/cli": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.3.tgz", + "integrity": "sha512-ULpF6Sbu2d7vNEOgBtE9avQp2oMgcPY/QBYcCqk0Xru5fz+ISjcovQX29V7CS7y5wWBRzNLoXwJQGeEyWbl05g==", + "dev": true, "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/typescript": "^4.0.9", - "@graphql-codegen/visitor-plugin-common": "5.3.1", + "@babel/generator": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/types": "^7.18.13", + "@graphql-codegen/client-preset": "^4.4.0", + "@graphql-codegen/core": "^4.0.2", + "@graphql-codegen/plugin-helpers": "^5.0.3", + "@graphql-tools/apollo-engine-loader": "^8.0.0", + "@graphql-tools/code-file-loader": "^8.0.0", + "@graphql-tools/git-loader": "^8.0.0", + "@graphql-tools/github-loader": "^8.0.0", + "@graphql-tools/graphql-file-loader": "^8.0.0", + "@graphql-tools/json-file-loader": "^8.0.0", + "@graphql-tools/load": "^8.0.0", + "@graphql-tools/prisma-loader": "^8.0.0", + "@graphql-tools/url-loader": "^8.0.0", + "@graphql-tools/utils": "^10.0.0", + "@whatwg-node/fetch": "^0.9.20", + "chalk": "^4.1.0", + "cosmiconfig": "^8.1.3", + "debounce": "^1.2.0", + "detect-indent": "^6.0.0", + "graphql-config": "^5.1.1", + "inquirer": "^8.0.0", + "is-glob": "^4.0.1", + "jiti": "^1.17.1", + "json-to-pretty-yaml": "^1.2.2", + "listr2": "^4.0.5", + "log-symbols": "^4.0.0", + "micromatch": "^4.0.5", + "shell-quote": "^1.7.3", + "string-env-interpolation": "^1.0.1", + "ts-log": "^2.2.3", + "tslib": "^2.4.0", + "yaml": "^2.3.1", + "yargs": "^17.0.0" + }, + "bin": { + "gql-gen": "cjs/bin.js", + "graphql-code-generator": "cjs/bin.js", + "graphql-codegen": "cjs/bin.js", + "graphql-codegen-esm": "esm/bin.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@parcel/watcher": "^2.1.0", + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "@parcel/watcher": { + "optional": true + } + } + }, + "node_modules/@graphql-codegen/cli/node_modules/@whatwg-node/fetch": { + "version": "0.9.22", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.22.tgz", + "integrity": "sha512-+RIBffgoaRlWV9cKV6wAX71sbeoU2APOI3G13ZRMkabYHwkvDMeZDTyxJcsMXA5CpieJ7NFXF9Xyu72jwvdzqA==", + "dev": true, + "dependencies": { + "@whatwg-node/node-fetch": "^0.5.27", + "urlpattern-polyfill": "^10.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/@whatwg-node/node-fetch": { + "version": "0.5.27", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.27.tgz", + "integrity": "sha512-0OaMj5W4fzWimRSFq07qFiWfquaUMNB+695GwE76LYKVuah+jwCdzSgsIOtwPkiyJ35w0XGhXmJPiIJCdLwopg==", + "dev": true, + "dependencies": { + "@kamilkisiela/fast-url-parser": "^1.1.4", + "busboy": "^1.6.0", + "fast-querystring": "^1.1.1", + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true + }, + "node_modules/@graphql-codegen/cli/node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true + }, + "node_modules/@graphql-codegen/client-preset": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.5.0.tgz", + "integrity": "sha512-0fFGSjpDhB7Jp6v+FQWDIeNJhL8VEiy3zeazyus3mGUELPaRQsoos2NczkDWnyMjSB1NHn4GrI53DB4TXkTAog==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7", + "@graphql-codegen/add": "^5.0.3", + "@graphql-codegen/gql-tag-operations": "4.0.11", + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/typed-document-node": "^5.0.11", + "@graphql-codegen/typescript": "^4.1.1", + "@graphql-codegen/typescript-operations": "^4.3.1", + "@graphql-codegen/visitor-plugin-common": "^5.5.0", + "@graphql-tools/documents": "^1.0.0", + "@graphql-tools/utils": "^10.0.0", + "@graphql-typed-document-node/core": "3.2.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/core": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz", + "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "@graphql-tools/schema": "^10.0.0", + "@graphql-tools/utils": "^10.0.0", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/gql-tag-operations": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.11.tgz", + "integrity": "sha512-EUQuBsYB5RtNlzBb/O0nJvbWC8HvPRWwVTHRf0ElOoQlJfRgfDom2GWmEM5hXa2afzMqB7AWxOH24ibOqiYnMQ==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/visitor-plugin-common": "5.5.0", "@graphql-tools/utils": "^10.0.0", "auto-bind": "~4.0.0", "tslib": "~2.6.0" }, + "engines": { + "node": ">=16" + }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/typescript-resolvers/node_modules/@graphql-codegen/visitor-plugin-common": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.3.1.tgz", - "integrity": "sha512-MktoBdNZhSmugiDjmFl1z6rEUUaqyxtFJYWnDilE7onkPgyw//O0M+TuPBJPBWdyV6J2ond0Hdqtq+rkghgSIQ==", + "node_modules/@graphql-codegen/plugin-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.1.0.tgz", + "integrity": "sha512-Y7cwEAkprbTKzVIe436TIw4w03jorsMruvCvu0HJkavaKMQbWY+lQ1RIuROgszDbxAyM35twB5/sUvYG5oW+yg==", "dev": true, "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-tools/optimize": "^2.0.0", - "@graphql-tools/relay-operation-optimizer": "^7.0.0", "@graphql-tools/utils": "^10.0.0", + "change-case-all": "1.0.15", + "common-tags": "1.8.2", + "import-from": "4.0.0", + "lodash": "~4.17.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/schema-ast": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.0.2.tgz", + "integrity": "sha512-5mVAOQQK3Oz7EtMl/l3vOQdc2aYClUzVDHHkMvZlunc+KlGgl81j8TLa+X7ANIllqU4fUEsQU3lJmk4hXP6K7Q==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "@graphql-tools/utils": "^10.0.0", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/typed-document-node": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.11.tgz", + "integrity": "sha512-btENKrSIUZ5UllS8sFhVZ+Y91VL0knK9gHxW/6/WzaCTxBQ+wOk07vQNeoWlvMrkl0QeUsGt6YvSo0SoPtsKdA==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/visitor-plugin-common": "5.5.0", "auto-bind": "~4.0.0", "change-case-all": "1.0.15", - "dependency-graph": "^0.11.0", - "graphql-tag": "^2.11.0", - "parse-filepath": "^1.0.2", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/typescript": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.1.1.tgz", + "integrity": "sha512-+o5LOT71K9hdO4lDVnRGkkET5RdlKvxlQGug8dZgRGrhE2/xoPBsKfLhg9AoJGYMauNZxKj3blABQxHOKEku6Q==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/schema-ast": "^4.0.2", + "@graphql-codegen/visitor-plugin-common": "5.5.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/typescript-operations": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.3.1.tgz", + "integrity": "sha512-yW5Iia6IK1VKiPm3oeukYMQN5pEBLwRlG8ZzQA9beeLQ8PskKyz6mjar6U7dJ2hc8pv/qT4R8kcJOQ2RloniAQ==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/typescript": "^4.1.1", + "@graphql-codegen/visitor-plugin-common": "5.5.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/typescript-resolvers": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-4.2.1.tgz", + "integrity": "sha512-q/ggqNSKNGG9bn49DdZrw2KokagDZmzl1EpxIfzmpHrPa3XaCLfxQuNNEUhqEXtJzQZtLfuYvGy1y+MrTU8WnA==", + "dev": true, + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-codegen/typescript": "^4.0.9", + "@graphql-codegen/visitor-plugin-common": "5.3.1", + "@graphql-tools/utils": "^10.0.0", + "auto-bind": "~4.0.0", "tslib": "~2.6.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/typescript/node_modules/@graphql-codegen/visitor-plugin-common": { + "node_modules/@graphql-codegen/typescript-resolvers/node_modules/@graphql-codegen/visitor-plugin-common": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.3.1.tgz", "integrity": "sha512-MktoBdNZhSmugiDjmFl1z6rEUUaqyxtFJYWnDilE7onkPgyw//O0M+TuPBJPBWdyV6J2ond0Hdqtq+rkghgSIQ==", @@ -2391,12 +3428,12 @@ } }, "node_modules/@graphql-codegen/visitor-plugin-common": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.1.0.tgz", - "integrity": "sha512-eamQxtA9bjJqI2lU5eYoA1GbdMIRT2X8m8vhWYsVQVWD3qM7sx/IqJU0kx0J3Vd4/CSd36BzL6RKwksibytDIg==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.5.0.tgz", + "integrity": "sha512-FSkxe/o4qKbpK+ipIT/jxZLYH0+3+XdIrJWsKlCW9wwJMF9mEJLJtzZNcxHSjz7+Eny6SUElAT2dqZ5XByxkog==", "dev": true, "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", + "@graphql-codegen/plugin-helpers": "^5.1.0", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.0.0", "@graphql-tools/utils": "^10.0.0", @@ -2407,6 +3444,9 @@ "parse-filepath": "^1.0.2", "tslib": "~2.6.0" }, + "engines": { + "node": ">=16" + }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } @@ -2416,6 +3456,7 @@ "resolved": "https://registry.npmjs.org/@graphql-eslint/eslint-plugin/-/eslint-plugin-3.20.1.tgz", "integrity": "sha512-RbwVlz1gcYG62sECR1u0XqMh8w5e5XMCCZoMvPQ3nJzEBCTfXLGX727GBoRmSvY1x4gJmqNZ1lsOX7lZY14RIw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", "@graphql-tools/code-file-loader": "^7.3.6", @@ -3370,9 +4411,9 @@ } }, "node_modules/@graphql-tools/documents": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.0.tgz", - "integrity": "sha512-rHGjX1vg/nZ2DKqRGfDPNC55CWZBMldEVcH+91BThRa6JeT80NqXknffLLEZLRUxyikCfkwMsk6xR3UNMqG0Rg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.1.tgz", + "integrity": "sha512-aweoMH15wNJ8g7b2r4C4WRuJxZ0ca8HtNO54rkye/3duxTkW4fGBEutCx03jCIr5+a1l+4vFJNP859QnAVBVCA==", "dev": true, "dependencies": { "lodash.sortby": "^4.7.0", @@ -3841,13 +4882,13 @@ } }, "node_modules/@graphql-tools/resolvers-composition": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/resolvers-composition/-/resolvers-composition-7.0.1.tgz", - "integrity": "sha512-EXcTi4OuGsj8UvQEleKVL4uJeOWc4MgOPK12qBCygkDMZArvBEzCa2IQ5Q9jWyCLcsNQxMXWyOm1rcQTrkJ+/w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/resolvers-composition/-/resolvers-composition-7.0.2.tgz", + "integrity": "sha512-ipTV1xjJSSx8iI0AQ5beZfUSlV08R8B+FGsbBnGCKiZ1Li4Y+egxR7wOcI9F3TlQlMExdSq3CjtoVfPpeYWsPw==", "dependencies": { - "@graphql-tools/utils": "^10.0.13", + "@graphql-tools/utils": "^10.5.5", "lodash": "4.17.21", - "micromatch": "^4.0.4", + "micromatch": "^4.0.8", "tslib": "^2.4.0" }, "engines": { @@ -3941,9 +4982,9 @@ "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" }, "node_modules/@graphql-tools/utils": { - "version": "10.5.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.5.4.tgz", - "integrity": "sha512-XHnyCWSlg1ccsD8s0y6ugo5GZ5TpkTiFVNPSYms5G0s6Z/xTuSmiLBfeqgkfaCwLmLaQnRCmNDL2JRnqc2R5bQ==", + "version": "10.5.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.5.5.tgz", + "integrity": "sha512-LF/UDWmMT0mnobL2UZETwYghV7HYBzNaGj0SAkCYOMy/C3+6sQdbcTksnoFaKR9XIVD78jNXEGfivbB8Zd+cwA==", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", "cross-inspect": "1.0.1", @@ -4024,52 +5065,19 @@ "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-yoga/typed-event-target": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@graphql-yoga/typed-event-target/-/typed-event-target-3.0.0.tgz", - "integrity": "sha512-w+liuBySifrstuHbFrHoHAEyVnDFVib+073q8AeAJ/qqJfvFvAwUPLLtNohR/WDVRgSasfXtl3dcNuVJWN+rjg==", - "dependencies": { - "@repeaterjs/repeater": "^3.0.4", - "tslib": "^2.5.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=16.0.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@graphql-yoga/typed-event-target": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@graphql-yoga/typed-event-target/-/typed-event-target-3.0.0.tgz", + "integrity": "sha512-w+liuBySifrstuHbFrHoHAEyVnDFVib+073q8AeAJ/qqJfvFvAwUPLLtNohR/WDVRgSasfXtl3dcNuVJWN+rjg==", "dependencies": { - "brace-expansion": "^1.1.7" + "@repeaterjs/repeater": "^3.0.4", + "tslib": "^2.5.2" }, "engines": { - "node": "*" + "node": ">=18.0.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -4084,10 +5092,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@ioredis/commands": { "version": "1.2.0", @@ -4335,25 +5351,24 @@ } }, "node_modules/@mui/base": { - "version": "5.0.0-alpha.112", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.112.tgz", - "integrity": "sha512-KPwb1iYPXsV/P8uu0SNQrj7v7YU6wdN4Eccc2lZQyRDW+f6PJYjHBuFUTYKc408B98Jvs1XbC/z5MN45a2DWrQ==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "@emotion/is-prop-valid": "^1.2.0", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.2", - "@popperjs/core": "^2.11.6", - "clsx": "^1.2.1", - "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "version": "5.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", + "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" }, "engines": { "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", @@ -4367,27 +5382,27 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz", - "integrity": "sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", + "integrity": "sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.0.tgz", - "integrity": "sha512-I2LaOKqO8a0xcLGtIozC9xoXjZAto5G5gh0FYUMAlbsIHNHIjn4Xrw9rvjY20vZonyiGrZNMAlAXYkY6JvhF6A==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.7.tgz", + "integrity": "sha512-UrGwDJCXEszbDI7yV047BYU5A28eGJ79keTCP4cc74WyncuVrnurlmIRxaHL8YK+LI1Kzq+/JM52IAkNnv4u+Q==", "dependencies": { - "@babel/runtime": "^7.20.6" + "@babel/runtime": "^7.23.9" }, "engines": { "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@mui/material": "^5.0.0", @@ -4401,30 +5416,29 @@ } }, "node_modules/@mui/lab": { - "version": "5.0.0-alpha.114", - "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.114.tgz", - "integrity": "sha512-tChDoLaJ3qcYk37GIwBL1KrCiW0gpmEY//D5z5nHWnO/mzx3axjRJZpBOBeGEvhuoO/Y3QzMz4rhTvqbGNkW0w==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "@mui/base": "5.0.0-alpha.112", - "@mui/system": "^5.11.2", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.2", - "clsx": "^1.2.1", - "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "version": "5.0.0-alpha.169", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.169.tgz", + "integrity": "sha512-h6xe1K6ISKUbyxTDgdvql4qoDP6+q8ad5fg9nXQxGLUrIeT2jVrBuT/jRECSTufbnhzP+V5kulvYxaMfM8rEdA==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/system": "^5.15.14", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" }, "engines": { "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material": "^5.0.0", + "@mui/material": ">=5.15.0", "@types/react": "^17.0.0 || ^18.0.0", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0" @@ -4442,21 +5456,21 @@ } }, "node_modules/@mui/material": { - "version": "5.11.2", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.2.tgz", - "integrity": "sha512-PeraRDsghnDLzejorfe9ps1syxlB8UrGs+UKwg9GGlndv5Tghm+9nwuibrP2TCDC14mlryF+u2WlAOYaPPMwGA==", - "dependencies": { - "@babel/runtime": "^7.20.7", - "@mui/base": "5.0.0-alpha.112", - "@mui/core-downloads-tracker": "^5.11.2", - "@mui/system": "^5.11.2", - "@mui/types": "^7.2.3", - "@mui/utils": "^5.11.2", - "@types/react-transition-group": "^4.4.5", - "clsx": "^1.2.1", - "csstype": "^3.1.1", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.7.tgz", + "integrity": "sha512-cwwVQxBhK60OIOqZOVLFt55t01zmarKJiJUWbk0+8s/Ix5IaUzAShqlJchxsIQ4mSrWqgcKCCXKtIlG5H+/Jmg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.7", + "@mui/system": "^5.16.7", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1", - "react-is": "^18.2.0", + "react-is": "^18.3.1", "react-transition-group": "^4.4.5" }, "engines": { @@ -4464,7 +5478,7 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", @@ -4486,12 +5500,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz", - "integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.15.14", + "@mui/utils": "^5.16.6", "prop-types": "^15.8.1" }, "engines": { @@ -4512,9 +5526,9 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz", - "integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", "dependencies": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", @@ -4543,15 +5557,15 @@ } }, "node_modules/@mui/system": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.14.tgz", - "integrity": "sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==", + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.15.14", - "@mui/styled-engine": "^5.15.14", - "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", + "@mui/private-theming": "^5.16.6", + "@mui/styled-engine": "^5.16.6", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -4581,20 +5595,12 @@ } } }, - "node_modules/@mui/system/node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "engines": { - "node": ">=6" - } - }, "node_modules/@mui/types": { - "version": "7.2.14", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz", - "integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==", + "version": "7.2.18", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.18.tgz", + "integrity": "sha512-uvK9dWeyCJl/3ocVnTOS6nlji/Knj8/tVqVX03UVTpdmTJYu/s4jtDd9Kvv0nRGE0CUSNW1UYAci7PYypjealg==", "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -4603,14 +5609,16 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.14", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz", - "integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==", + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", "dependencies": { "@babel/runtime": "^7.23.9", - "@types/prop-types": "^15.7.11", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "react-is": "^18.3.1" }, "engines": { "node": ">=12.0.0" @@ -4669,249 +5677,29 @@ "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.4.1", - "@parcel/watcher-darwin-arm64": "2.4.1", - "@parcel/watcher-darwin-x64": "2.4.1", - "@parcel/watcher-freebsd-x64": "2.4.1", - "@parcel/watcher-linux-arm-glibc": "2.4.1", - "@parcel/watcher-linux-arm64-glibc": "2.4.1", - "@parcel/watcher-linux-arm64-musl": "2.4.1", - "@parcel/watcher-linux-x64-glibc": "2.4.1", - "@parcel/watcher-linux-x64-musl": "2.4.1", - "@parcel/watcher-win32-arm64": "2.4.1", - "@parcel/watcher-win32-ia32": "2.4.1", - "@parcel/watcher-win32-x64": "2.4.1" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", - "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", - "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", - "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", - "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", - "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", - "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", - "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", - "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", - "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", - "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", - "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, "engines": { "node": ">= 10.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" } }, "node_modules/@parcel/watcher-win32-x64": { @@ -5309,5693 +6097,5981 @@ "integrity": "sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, - "node_modules/@shikijs/core": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", - "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", - "peer": true, - "dependencies": { - "@types/hast": "^3.0.4" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" - }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" - }, - "node_modules/@types/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bcryptjs": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", - "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", - "dev": true - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/busboy": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.3.tgz", - "integrity": "sha512-YMBLFN/xBD8bnqywIlGyYqsNFXu6bsiY7h3Ae0kO17qEuTjsqeyYMRPSUDacIKIquws2Y6KjmxAyNx8xB3xQbw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cls-hooked": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.8.tgz", - "integrity": "sha512-tf/7H883gFA6MPlWI15EQtfNZ+oPL0gLKkOlx9UHFrun1fC/FkuyNBpTKq1B5E3T4fbvjId6WifHUdSGsMMuPg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/content-disposition": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.8.tgz", - "integrity": "sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==" - }, - "node_modules/@types/cookies": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.9.0.tgz", - "integrity": "sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==", - "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "node_modules/@types/copy-paste": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/@types/copy-paste/-/copy-paste-1.1.33.tgz", - "integrity": "sha512-vhDsD3A+WPfme1SW56fZCPvgEQ6ELYC0Jzgomldg+ExpMyQ1xDcIcuzao6O5l43cttbhepo16zz54Y16+GtpKw==", - "dev": true - }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-rate-limit": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-6.0.0.tgz", - "integrity": "sha512-nZxo3nwU20EkTl/f2eGdndQkDIJYwkXIX4S3Vrp2jMdSdFJ6AWtIda8gOz0wiMuOFoeH/UUlCAiacz3x3eWNFA==", - "deprecated": "This is a stub types definition. express-rate-limit provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "express-rate-limit": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.43", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", - "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/graphql-depth-limit": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@types/graphql-depth-limit/-/graphql-depth-limit-1.1.6.tgz", - "integrity": "sha512-WU4bjoKOzJ8CQE32Pbyq+YshTMcLJf2aJuvVtSLv1BQPwDUGa38m2Vr8GGxf0GZ0luCQcfxlhZeHKu6nmTBvrw==", - "dev": true, - "dependencies": { - "graphql": "^14.5.3" - } - }, - "node_modules/@types/graphql-depth-limit/node_modules/graphql": { - "version": "14.7.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", - "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", - "dev": true, - "dependencies": { - "iterall": "^1.2.2" - }, - "engines": { - "node": ">= 6.x" - } - }, - "node_modules/@types/graphql-upload": { - "version": "16.0.7", - "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-16.0.7.tgz", - "integrity": "sha512-7vCoxIv2pVTvV8n+miYyfkINdguWsYomAkPlOfHoM6z/qzsiBAdfRb6lNc8PvEUhe7TXaxX4+LHubejw1og1DQ==", - "dependencies": { - "@types/express": "*", - "@types/koa": "*", - "@types/node": "*", - "fs-capacitor": "^8.0.0", - "graphql": "^16.3.0" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "peer": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/http-assert": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.5.tgz", - "integrity": "sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" - }, - "node_modules/@types/i18n": { - "version": "0.13.12", - "resolved": "https://registry.npmjs.org/@types/i18n/-/i18n-0.13.12.tgz", - "integrity": "sha512-iAd2QjKh+0ToBXocmCS3m38GskiaGzmSV1MTQz2GaOraqSqBiLf46J7u3EGINl+st+Uk4lO3OL7QyIjTJlrWIg==", - "dev": true - }, - "node_modules/@types/inquirer": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", - "integrity": "sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==", - "dev": true, - "dependencies": { - "@types/through": "*", - "rxjs": "^7.2.0" - } - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true - }, - "node_modules/@types/json-stable-stringify": { - "version": "1.0.36", - "resolved": "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.36.tgz", - "integrity": "sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", "dev": true }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", - "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", - "dev": true, + "node_modules/@shikijs/core": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", + "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", + "peer": true, "dependencies": { - "@types/node": "*" + "@types/hast": "^3.0.4" } }, - "node_modules/@types/keygrip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", - "integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==" - }, - "node_modules/@types/koa": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.15.0.tgz", - "integrity": "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==", + "node_modules/@smithy/abort-controller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.5.tgz", + "integrity": "sha512-DhNPnqTqPoG8aZ5dWkFOgsuY+i0GQ3CI6hMmvCoduNsnU9gUZWZBwGfDQsTTB7NvFPkom1df7jMIJWU90kuXXg==", "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/koa-compose": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.8.tgz", - "integrity": "sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==", + "node_modules/@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", "dependencies": { - "@types/koa": "*" + "tslib": "^2.6.2" } }, - "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", - "dev": true, - "license": "MIT" + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } }, - "node_modules/@types/long": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + "node_modules/@smithy/config-resolver": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.9.tgz", + "integrity": "sha512-5d9oBf40qC7n2xUoHmntKLdqsyTMMo/r49+eqSIjJ73eDfEtljAxEhzIQ3bkgXJtR3xiv7YzMT/3FF3ORkjWdg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + "node_modules/@smithy/core": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.8.tgz", + "integrity": "sha512-x4qWk7p/a4dcf7Vxb2MODIf4OIcqNbK182WxRvZ/3oKPrf/6Fdic5sSElhO1UtXpWKBazWfqg0ZEK9xN1DsuHA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/mongoose-paginate-v2": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@types/mongoose-paginate-v2/-/mongoose-paginate-v2-1.6.5.tgz", - "integrity": "sha512-OdnsqewLwCtZvExUHuL+KDVlZ6OdnzGcUdPpEqMRVKZ6mWy7fgnt1IkLSs8Zugv5cUTLVT46hjmL2OPWtml1Rw==", - "deprecated": "This is a stub types definition. mongoose-paginate-v2 provides its own type definitions, so you do not need this installed.", - "dev": true, + "node_modules/@smithy/credential-provider-imds": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.4.tgz", + "integrity": "sha512-S9bb0EIokfYEuar4kEbLta+ivlKCWOCFsLZuilkNy9i0uEUEHSi47IFLPaxqqCl+0ftKmcOTHayY5nQhAuq7+w==", "dependencies": { - "mongoose-paginate-v2": "*" + "@smithy/node-config-provider": "^3.1.8", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/morgan": { - "version": "1.9.9", - "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", - "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", - "dev": true, + "node_modules/@smithy/eventstream-codec": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.6.tgz", + "integrity": "sha512-SBiOYPBH+5wOyPS7lfI150ePfGLhnp/eTu5RnV9xvhGvRiKfnl6HzRK9wehBph+il8FxS9KTeadx7Rcmf1GLPQ==", "dependencies": { - "@types/node": "*" + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.5.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.10.tgz", + "integrity": "sha512-1i9aMY6Pl/SmA6NjvidxnfBLHMPzhKu2BP148pEt5VwhMdmXn36PE2kWKGa9Hj8b0XGtCTRucpCncylevCtI7g==", "dependencies": { - "undici-types": "~6.19.2" + "@smithy/eventstream-serde-universal": "^3.0.9", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.7.tgz", + "integrity": "sha512-eVzhGQBPEqXXYHvIUku0jMTxd4gDvenRzUQPTmKVWdRvp9JUCKrbAXGQRYiGxUYq9+cqQckRm0wq3kTWnNtDhw==", "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/nodemailer": { - "version": "6.4.15", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.15.tgz", - "integrity": "sha512-0EBJxawVNjPkng1zm2vopRctuWVCxk34JcIlRuXSf54habUWdz1FB7wHDqOqvDa8Mtpt0Q3LTXQkAs2LNyK5jQ==", - "dev": true, + "node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.9.tgz", + "integrity": "sha512-JE0Guqvt0xsmfQ5y1EI342/qtJqznBv8cJqkHZV10PwC8GWGU5KNgFbQnsVCcX+xF+qIqwwfRmeWoJCjuOLmng==", "dependencies": { - "@types/node": "*" + "@smithy/eventstream-serde-universal": "^3.0.9", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/@types/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha512-4tgJ1Z3elF/tOMpA8JLVuR9spt9Ynsf7+JjqsQ2IqtiPJtcLoHoXcT6qU4E10cPFqyXX5HDm9QwIzZhBSkLxsw==" - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" - }, - "node_modules/@types/qs": { - "version": "6.9.14", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", - "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" - }, - "node_modules/@types/react": { - "version": "18.2.69", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.69.tgz", - "integrity": "sha512-W1HOMUWY/1Yyw0ba5TkCV+oqynRjG7BnteBB+B7JmAK7iw3l2SW+VGOxL+akPweix6jk2NNJtyJKpn4TkpfK3Q==", + "node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.9.tgz", + "integrity": "sha512-bydfgSisfepCufw9kCEnWRxqxJFzX/o8ysXWv+W9F2FIyiaEwZ/D8bBKINbh4ONz3i05QJ1xE7A5OKYvgJsXaw==", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "@smithy/eventstream-codec": "^3.1.6", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "node_modules/@smithy/fetch-http-handler": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.9.tgz", + "integrity": "sha512-hYNVQOqhFQ6vOpenifFME546f0GfJn2OiQ3M0FDmuUu8V/Uiwy2wej7ZXxFBNqdx0R5DZAqWM1l6VRhGz8oE6A==", "dependencies": { - "@types/react": "*" + "@smithy/protocol-http": "^4.1.4", + "@smithy/querystring-builder": "^3.0.7", + "@smithy/types": "^3.5.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/@smithy/hash-blob-browser": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.6.tgz", + "integrity": "sha512-BKNcMIaeZ9lB67sgo88iCF4YB35KT8X2dNJ8DqrtZNTgN6tUDYBKThzfGtos/mnZkGkW91AYHisESHmSiYQmKw==", "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" } }, - "node_modules/@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "node_modules/@smithy/hash-node": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.7.tgz", + "integrity": "sha512-SAGHN+QkrwcHFjfWzs/czX94ZEjPJ0CrWJS3M43WswDXVEuP4AVy9gJ3+AF6JQHZD13bojmuf/Ap/ItDeZ+Qfw==", "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@smithy/types": "^3.5.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/through": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", - "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", - "dev": true, + "node_modules/@smithy/hash-stream-node": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.6.tgz", + "integrity": "sha512-sFSSt7cmCpFWZPfVx7k80Bgb1K2VJ27VmMxH8X+dDhp7Wv8IBgID4K2VK5ehMJROF8hQgcj4WywnkHIwX/xlwQ==", "dependencies": { - "@types/node": "*" + "@smithy/types": "^3.5.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" - }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "peer": true - }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.7.tgz", + "integrity": "sha512-Bq00GsAhHeYSuZX8Kpu4sbI9agH2BNYnqUmmbTGWOhki9NVsWn2jFr896vvoTMH8KAjNX/ErC/8t5QHuEXG+IA==", + "dependencies": { + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + } }, - "node_modules/@types/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==", - "dev": true + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + "node_modules/@smithy/md5-js": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.7.tgz", + "integrity": "sha512-+wco9IN9uOW4tNGkZIqTR6IXyfO7Z8A+IOq82QCRn/f/xcmt7H1fXwmQVbfDSvbeFwfNnhv7s+u0G9PzPG6o2w==", + "dependencies": { + "@smithy/types": "^3.5.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } }, - "node_modules/@types/whatwg-url": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", - "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.9.tgz", + "integrity": "sha512-t97PidoGElF9hTtLCrof32wfWMqC5g2SEJNxaVH3NjlatuNGsdxXRYO/t+RPnxA15RpYiS0f+zG7FuE2DeGgjA==", "dependencies": { - "@types/webidl-conversions": "*" + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "node_modules/@smithy/middleware-endpoint": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.4.tgz", + "integrity": "sha512-/ChcVHekAyzUbyPRI8CzPPLj6y8QRAfJngWcLMgsWxKVzw/RzBV69mSOzJYDD3pRwushA1+5tHtPF8fjmzBnrQ==", "dependencies": { - "@types/node": "*" + "@smithy/middleware-serde": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", + "@smithy/util-middleware": "^3.0.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "node_modules/@smithy/middleware-retry": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.23.tgz", + "integrity": "sha512-x9PbGXxkcXIpm6L26qRSCC+eaYcHwybRmqU8LO/WM2RRlW0g8lz6FIiKbKgGvHuoK3dLZRiQVSQJveiCzwnA5A==", "dependencies": { - "@types/yargs-parser": "*" + "@smithy/node-config-provider": "^3.1.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/service-error-classification": "^3.0.7", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.2.0.tgz", - "integrity": "sha512-02tJIs655em7fvt9gps/+4k4OsKULYGtLBPJfOsmOq1+3cdClYiF0+d6mHu6qDnTcg88wJBkcPLpQhq7FyDz0A==", + "node_modules/@smithy/middleware-serde": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.7.tgz", + "integrity": "sha512-VytaagsQqtH2OugzVTq4qvjkLNbWehHfGcGr0JLJmlDRrNCeZoWkWsSOw1nhS/4hyUUWF/TLGGml4X/OnEep5g==", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.2.0", - "@typescript-eslint/type-utils": "8.2.0", - "@typescript-eslint/utils": "8.2.0", - "@typescript-eslint/visitor-keys": "8.2.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.2.0.tgz", - "integrity": "sha512-OFn80B38yD6WwpoHU2Tz/fTz7CgFqInllBoC3WP+/jLbTb4gGPTy9HBSTsbDWkMdN55XlVU0mMDYAtgvlUspGw==", + "node_modules/@smithy/middleware-stack": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.7.tgz", + "integrity": "sha512-EyTbMCdqS1DoeQsO4gI7z2Gzq1MoRFAeS8GkFYIwbedB7Lp5zlLHJdg+56tllIIG5Hnf9ZWX48YKSHlsKvugGA==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "@typescript-eslint/visitor-keys": "8.2.0" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", - "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node_modules/@smithy/node-config-provider": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.8.tgz", + "integrity": "sha512-E0rU0DglpeJn5ge64mk8wTGEXcQwmpUTY5Zr7IzTpDLmHKiIamINERNZYrPQjg58Ck236sEKSwRSHA4CwshU6Q==", + "dependencies": { + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", - "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", + "node_modules/@smithy/node-http-handler": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.4.tgz", + "integrity": "sha512-49reY3+JgLMFNm7uTAKBWiKCA6XSvkNp9FqhVmusm2jpVnHORYFeFZ704LShtqWfjZW/nhX+7Iexyb6zQfXYIQ==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "eslint-visitor-keys": "^3.4.3" + "@smithy/abort-controller": "^3.1.5", + "@smithy/protocol-http": "^4.1.4", + "@smithy/querystring-builder": "^3.0.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.1.tgz", - "integrity": "sha512-5IgYJ9EO/12pOUwiBKFkpU7rS3IU21mtXzB81TNwq2xEybcmAZrE9qwDtsb5uQd9aVO9o0fdabFyAmKveXyujg==", + "node_modules/@smithy/property-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.7.tgz", + "integrity": "sha512-QfzLi1GPMisY7bAM5hOUqBdGYnY5S2JAlr201pghksrQv139f8iiiMalXtjczIP5f6owxFn3MINLNUNvUkgtPw==", "dependencies": { - "@typescript-eslint/scope-manager": "8.0.1", - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/typescript-estree": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1", - "debug": "^4.3.4" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", - "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", + "node_modules/@smithy/protocol-http": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.4.tgz", + "integrity": "sha512-MlWK8eqj0JlpZBnWmjQLqmFp71Ug00P+m72/1xQB3YByXD4zZ+y9N4hYrR0EDmrUCZIkyATWHOXFgtavwGDTzQ==", "dependencies": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.1" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.2.0.tgz", - "integrity": "sha512-g1CfXGFMQdT5S+0PSO0fvGXUaiSkl73U1n9LTK5aRAFnPlJ8dLKkXr4AaLFvPedW8lVDoMgLLE3JN98ZZfsj0w==", + "node_modules/@smithy/querystring-builder": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.7.tgz", + "integrity": "sha512-65RXGZZ20rzqqxTsChdqSpbhA6tdt5IFNgG6o7e1lnPVLCe6TNWQq4rTl4N87hTDD8mV4IxJJnvyE7brbnRkQw==", "dependencies": { - "@typescript-eslint/typescript-estree": "8.2.0", - "@typescript-eslint/utils": "8.2.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@smithy/types": "^3.5.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", - "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node_modules/@smithy/querystring-parser": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.7.tgz", + "integrity": "sha512-Fouw4KJVWqqUVIu1gZW8BH2HakwLz6dvdrAhXeXfeymOBrZw+hcqaWs+cS1AZPVp4nlbeIujYrKA921ZW2WMPA==", + "dependencies": { + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.2.0.tgz", - "integrity": "sha512-kiG4EDUT4dImplOsbh47B1QnNmXSoUqOjWDvCJw/o8LgfD0yr7k2uy54D5Wm0j4t71Ge1NkynGhpWdS0dEIAUA==", + "node_modules/@smithy/service-error-classification": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.7.tgz", + "integrity": "sha512-91PRkTfiBf9hxkIchhRKJfl1rsplRDyBnmyFca3y0Z3x/q0JJN480S83LBd8R6sBCkm2bBbqw2FHp0Mbh+ecSA==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "@typescript-eslint/visitor-keys": "8.2.0", - "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" + "@smithy/types": "^3.5.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", - "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.8.tgz", + "integrity": "sha512-0NHdQiSkeGl0ICQKcJQ2lCOKH23Nb0EaAa7RDRId6ZqwXkw4LJyIyZ0t3iusD4bnKYDPLGy2/5e2rfUhrt0Acw==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "eslint-visitor-keys": "^3.4.3" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@smithy/signature-v4": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.0.tgz", + "integrity": "sha512-LafbclHNKnsorMgUkKm7Tk7oJ7xizsZ1VwqhGKqoCIrXh4fqDDp73fK99HOEEgcsQbtemmeY/BPv0vTVYYUNEQ==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", - "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node_modules/@smithy/smithy-client": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.4.0.tgz", + "integrity": "sha512-nOfJ1nVQsxiP6srKt43r2My0Gp5PLWCW2ASqUioxIiGmu6d32v4Nekidiv5qOmmtzIrmaD+ADX5SKHUuhReeBQ==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", + "@smithy/util-stream": "^3.1.9", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", - "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", + "node_modules/@smithy/types": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.5.0.tgz", + "integrity": "sha512-QN0twHNfe8mNJdH9unwsCK13GURU7oEAZqkBI+rsvpv1jrmserO+WnLE7jidR9W/1dxwZ0u/CB01mV2Gms/K2Q==", "dependencies": { - "@typescript-eslint/types": "8.0.1", - "@typescript-eslint/visitor-keys": "8.0.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" + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.7.tgz", + "integrity": "sha512-70UbSSR8J97c1rHZOWhl+VKiZDqHWxs/iW8ZHrHp5fCCPLSBE7GcUlUvKSle3Ca+J9LLbYCj/A79BxztBvAfpA==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.2.0.tgz", - "integrity": "sha512-O46eaYKDlV3TvAVDNcoDzd5N550ckSe8G4phko++OCSC1dYIb9LTc3HDGYdWqWIAT5qDUKphO6sd9RrpIJJPfg==", + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.2.0", - "@typescript-eslint/types": "8.2.0", - "@typescript-eslint/typescript-estree": "8.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.23.tgz", + "integrity": "sha512-Y07qslyRtXDP/C5aWKqxTPBl4YxplEELG3xRrz2dnAQ6Lq/FgNrcKWmV561nNaZmFH+EzeGOX3ZRMbU8p1T6Nw==", + "dependencies": { + "@smithy/property-provider": "^3.1.7", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.23.tgz", + "integrity": "sha512-9Y4WH7f0vnDGuHUa4lGX9e2p+sMwODibsceSV6rfkZOvMC+BY3StB2LdO1NHafpsyHJLpwAgChxQ38tFyd6vkg==", + "dependencies": { + "@smithy/config-resolver": "^3.0.9", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/property-provider": "^3.1.7", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.2.0.tgz", - "integrity": "sha512-OFn80B38yD6WwpoHU2Tz/fTz7CgFqInllBoC3WP+/jLbTb4gGPTy9HBSTsbDWkMdN55XlVU0mMDYAtgvlUspGw==", + "node_modules/@smithy/util-endpoints": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.3.tgz", + "integrity": "sha512-34eACeKov6jZdHqS5hxBMJ4KyWKztTMulhuQ2UdOoP6vVxMLrOKUqIXAwJe/wiWMhXhydLW664B02CNpQBQ4Aw==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "@typescript-eslint/visitor-keys": "8.2.0" + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", - "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.2.0.tgz", - "integrity": "sha512-kiG4EDUT4dImplOsbh47B1QnNmXSoUqOjWDvCJw/o8LgfD0yr7k2uy54D5Wm0j4t71Ge1NkynGhpWdS0dEIAUA==", + "node_modules/@smithy/util-middleware": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.7.tgz", + "integrity": "sha512-OVA6fv/3o7TMJTpTgOi1H5OTwnuUa8hzRzhSFDtZyNxi6OZ70L/FHattSmhE212I7b6WSOJAAmbYnvcjTHOJCA==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "@typescript-eslint/visitor-keys": "8.2.0", - "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" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", - "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", + "node_modules/@smithy/util-retry": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.7.tgz", + "integrity": "sha512-nh1ZO1vTeo2YX1plFPSe/OXaHkLAHza5jpokNiiKX2M5YpNUv6RxGJZhpfmiR4jSvVHCjIDmILjrxKmP+/Ghug==", "dependencies": { - "@typescript-eslint/types": "8.2.0", - "eslint-visitor-keys": "^3.4.3" + "@smithy/service-error-classification": "^3.0.7", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.9.tgz", + "integrity": "sha512-7YAR0Ub3MwTMjDfjnup4qa6W8gygZMxikBhFMPESi6ASsl/rZJhwLpF/0k9TuezScCojsM0FryGdz4LZtjKPPQ==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/types": "^3.5.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", - "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dependencies": { - "@typescript-eslint/types": "8.0.1", - "eslint-visitor-keys": "^3.4.3" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.1.6.tgz", + "integrity": "sha512-xs/KAwWOeCklq8aMlnpk25LgxEYHKOEodfjfKclDMLcBJEVEKzDLxZxBQyztcuPJ7F54213NJS8PxoiHNMdItQ==", + "dependencies": { + "@smithy/abort-controller": "^3.1.5", + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" }, - "node_modules/@vitest/coverage-v8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.1.tgz", - "integrity": "sha512-md/A7A3c42oTT8JUHSqjP5uKTWJejzUW4jalpvs+rZ27gsURsMU8DEb+8Jf8C6Kj2gwfSHJqobDNBuoqlm0cFw==", + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, + "node_modules/@types/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/busboy": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.3.tgz", + "integrity": "sha512-YMBLFN/xBD8bnqywIlGyYqsNFXu6bsiY7h3Ae0kO17qEuTjsqeyYMRPSUDacIKIquws2Y6KjmxAyNx8xB3xQbw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cls-hooked": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.9.tgz", + "integrity": "sha512-CMtHMz6Q/dkfcHarq9nioXH8BDPP+v5xvd+N90lBQ2bdmu06UvnLDqxTKoOJzz4SzIwb/x9i4UXGAAcnUDuIvg==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.6", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.6", - "istanbul-reports": "^3.1.7", - "magic-string": "^0.30.11", - "magicast": "^0.3.4", - "std-env": "^3.7.0", - "test-exclude": "^7.0.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "2.1.1", - "vitest": "2.1.1" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } + "@types/node": "*" } }, - "node_modules/@vitest/expect": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.1.tgz", - "integrity": "sha512-YeueunS0HiHiQxk+KEOnq/QMzlUuOzbU1Go+PgAsHvvv3tUkJPm9xWt+6ITNTlzsMXUjmgm5T+U7KBPK2qQV6w==", + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/content-disposition": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.8.tgz", + "integrity": "sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==" + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true + }, + "node_modules/@types/cookies": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.9.0.tgz", + "integrity": "sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==", + "dependencies": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "node_modules/@types/copy-paste": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/@types/copy-paste/-/copy-paste-1.1.33.tgz", + "integrity": "sha512-vhDsD3A+WPfme1SW56fZCPvgEQ6ELYC0Jzgomldg+ExpMyQ1xDcIcuzao6O5l43cttbhepo16zz54Y16+GtpKw==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dev": true, "dependencies": { - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", - "chai": "^5.1.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@types/node": "*" } }, - "node_modules/@vitest/mocker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.1.tgz", - "integrity": "sha512-LNN5VwOEdJqCmJ/2XJBywB11DLlkbY0ooDJW3uRX5cZyYCrc4PI/ePX0iQhE3BiEGiQmK4GE7Q/PqCkkaiPnrA==", + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-rate-limit": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/express-rate-limit/-/express-rate-limit-6.0.2.tgz", + "integrity": "sha512-e1xZLOOlxCDvplAGq7rDcXtbdBu2CWRsMjaIu1LVqGxWtKvwr884YE5mPs3IvHeG/OMDhf24oTaqG5T1bV3rBQ==", + "deprecated": "This is a stub types definition. express-rate-limit provides its own type definitions, so you do not need this installed.", "dev": true, "dependencies": { - "@vitest/spy": "^2.1.0-beta.1", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.11" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/spy": "2.1.1", - "msw": "^2.3.5", - "vite": "^5.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } + "express-rate-limit": "*" } }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.1.tgz", - "integrity": "sha512-SjxPFOtuINDUW8/UkElJYQSFtnWX7tMksSGW0vfjxMneFqxVr8YJ979QpMbDW7g+BIiq88RAGDjf7en6rvLPPQ==", - "dev": true, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.43", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz", + "integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==", "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/@vitest/runner": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.1.tgz", - "integrity": "sha512-uTPuY6PWOYitIkLPidaY5L3t0JJITdGTSwBtwMjKzo5O6RCOEncz9PUN+0pDidX8kTHYjO0EwUIvhlGpnGpxmA==", + "node_modules/@types/graphql-depth-limit": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@types/graphql-depth-limit/-/graphql-depth-limit-1.1.6.tgz", + "integrity": "sha512-WU4bjoKOzJ8CQE32Pbyq+YshTMcLJf2aJuvVtSLv1BQPwDUGa38m2Vr8GGxf0GZ0luCQcfxlhZeHKu6nmTBvrw==", "dev": true, "dependencies": { - "@vitest/utils": "2.1.1", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "graphql": "^14.5.3" } }, - "node_modules/@vitest/snapshot": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.1.tgz", - "integrity": "sha512-BnSku1WFy7r4mm96ha2FzN99AZJgpZOWrAhtQfoxjUU5YMRpq1zmHRq7a5K9/NjqonebO7iVDla+VvZS8BOWMw==", + "node_modules/@types/graphql-depth-limit/node_modules/graphql": { + "version": "14.7.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", + "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", "dev": true, "dependencies": { - "@vitest/pretty-format": "2.1.1", - "magic-string": "^0.30.11", - "pathe": "^1.1.2" + "iterall": "^1.2.2" }, - "funding": { - "url": "https://opencollective.com/vitest" + "engines": { + "node": ">= 6.x" } }, - "node_modules/@vitest/spy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.1.tgz", - "integrity": "sha512-ZM39BnZ9t/xZ/nF4UwRH5il0Sw93QnZXd9NAZGRpIgj0yvVwPpLd702s/Cx955rGaMlyBQkZJ2Ir7qyY48VZ+g==", - "dev": true, + "node_modules/@types/graphql-upload": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-16.0.7.tgz", + "integrity": "sha512-7vCoxIv2pVTvV8n+miYyfkINdguWsYomAkPlOfHoM6z/qzsiBAdfRb6lNc8PvEUhe7TXaxX4+LHubejw1og1DQ==", "dependencies": { - "tinyspy": "^3.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@types/express": "*", + "@types/koa": "*", + "@types/node": "*", + "fs-capacitor": "^8.0.0", + "graphql": "^16.3.0" } }, - "node_modules/@vitest/utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.1.tgz", - "integrity": "sha512-Y6Q9TsI+qJ2CC0ZKj6VBb+T8UPz593N113nnUykqwANqhgf3QkZeHFlusgKLTqrnVHbj/XDKZcDHol+dxVT+rQ==", - "dev": true, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "peer": true, "dependencies": { - "@vitest/pretty-format": "2.1.1", - "loupe": "^3.1.1", - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@types/unist": "*" } }, - "node_modules/@whatwg-node/events": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", - "integrity": "sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==", + "node_modules/@types/http-assert": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.5.tgz", + "integrity": "sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/i18n": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/@types/i18n/-/i18n-0.13.12.tgz", + "integrity": "sha512-iAd2QjKh+0ToBXocmCS3m38GskiaGzmSV1MTQz2GaOraqSqBiLf46J7u3EGINl+st+Uk4lO3OL7QyIjTJlrWIg==", "dev": true }, - "node_modules/@whatwg-node/fetch": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.8.8.tgz", - "integrity": "sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==", + "node_modules/@types/inquirer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.7.tgz", + "integrity": "sha512-Q0zyBupO6NxGRZut/JdmqYKOnN95Eg5V8Csg3PGKkP+FnvsUZx1jAyK7fztIszxxMuoBA6E3KXWvdZVXIpx60g==", "dev": true, "dependencies": { - "@peculiar/webcrypto": "^1.4.0", - "@whatwg-node/node-fetch": "^0.3.6", - "busboy": "^1.6.0", - "urlpattern-polyfill": "^8.0.0", - "web-streams-polyfill": "^3.2.1" + "@types/through": "*", + "rxjs": "^7.2.0" } }, - "node_modules/@whatwg-node/node-fetch": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz", - "integrity": "sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==", - "dev": true, - "dependencies": { - "@whatwg-node/events": "^0.0.3", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", - "tslib": "^2.3.1" - } + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true }, - "node_modules/@whatwg-node/server": { - "version": "0.9.34", - "resolved": "https://registry.npmjs.org/@whatwg-node/server/-/server-0.9.34.tgz", - "integrity": "sha512-1sHRjqUtZIyTR2m2dS/dJpzS5OcNDpPuUSVDa2PoEgzYVKr4GsqJaYtRaEXXFohvvyh6PkouYCc1rE7jMDWVCA==", + "node_modules/@types/json-stable-stringify": { + "version": "1.0.36", + "resolved": "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.36.tgz", + "integrity": "sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "dev": true, "dependencies": { - "@whatwg-node/fetch": "^0.9.17", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" + "@types/node": "*" } }, - "node_modules/@whatwg-node/server/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", - "engines": { - "node": ">=16.0.0" - } + "node_modules/@types/keygrip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", + "integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==" }, - "node_modules/@whatwg-node/server/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", + "node_modules/@types/koa": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.15.0.tgz", + "integrity": "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==", "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0" + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/http-errors": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" } }, - "node_modules/@whatwg-node/server/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", + "node_modules/@types/koa-compose": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.8.tgz", + "integrity": "sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==", "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" + "@types/koa": "*" } }, - "node_modules/@whatwg-node/server/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" + "node_modules/@types/lodash": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", + "dev": true }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/mongoose-paginate-v2": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/@types/mongoose-paginate-v2/-/mongoose-paginate-v2-1.6.5.tgz", + "integrity": "sha512-OdnsqewLwCtZvExUHuL+KDVlZ6OdnzGcUdPpEqMRVKZ6mWy7fgnt1IkLSs8Zugv5cUTLVT46hjmL2OPWtml1Rw==", + "deprecated": "This is a stub types definition. mongoose-paginate-v2 provides its own type definitions, so you do not need this installed.", + "dev": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" + "mongoose-paginate-v2": "*" } }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "node_modules/@types/morgan": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.9.tgz", + "integrity": "sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node_modules/@types/multer": { + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.12.tgz", + "integrity": "sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==", + "dev": true, + "dependencies": { + "@types/express": "*" } }, - "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "node_modules/@types/node": { + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" + "undici-types": "~6.19.8" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/nodemailer": { + "version": "6.4.16", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.16.tgz", + "integrity": "sha512-uz6hN6Pp0upXMcilM61CoKyjT7sskBoOWpptkjjJp8jIMlTdc3xG01U7proKkXzruMS4hS0zqtHNkNPFB20rKQ==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@types/node": "*" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@types/object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/@types/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha512-4tgJ1Z3elF/tOMpA8JLVuR9spt9Ynsf7+JjqsQ2IqtiPJtcLoHoXcT6qU4E10cPFqyXX5HDm9QwIzZhBSkLxsw==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + }, + "node_modules/@types/qs": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/react": { + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "@types/prop-types": "*", + "csstype": "^3.0.2" } }, - "node_modules/amp": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", - "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==" + "node_modules/@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "dependencies": { + "@types/react": "*" + } }, - "node_modules/amp-message": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", - "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==", + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dependencies": { - "amp": "0.3.1" + "@types/mime": "^1", + "@types/node": "*" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@types/superagent": { + "version": "8.1.9", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", + "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" } }, - "node_modules/ansi-red": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", - "integrity": "sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==", + "node_modules/@types/supertest": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", + "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", + "dev": true, "dependencies": { - "ansi-wrap": "0.1.0" - }, - "engines": { - "node": ">=0.10.0" + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node_modules/@types/through": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "peer": true + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "dev": true + }, + "node_modules/@types/validator": { + "version": "13.12.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.2.tgz", + "integrity": "sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==", + "dev": true + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@types/webidl-conversions": "*" } }, - "node_modules/ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", - "engines": { - "node": ">=0.10.0" + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dependencies": { + "@types/node": "*" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "@types/yargs-parser": "*" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.2.0.tgz", + "integrity": "sha512-02tJIs655em7fvt9gps/+4k4OsKULYGtLBPJfOsmOq1+3cdClYiF0+d6mHu6qDnTcg88wJBkcPLpQhq7FyDz0A==", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.2.0", + "@typescript-eslint/type-utils": "8.2.0", + "@typescript-eslint/utils": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "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" + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.2.0.tgz", + "integrity": "sha512-OFn80B38yD6WwpoHU2Tz/fTz7CgFqInllBoC3WP+/jLbTb4gGPTy9HBSTsbDWkMdN55XlVU0mMDYAtgvlUspGw==", + "dependencies": { + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", + "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", + "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", "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" + "@typescript-eslint/types": "8.2.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "node_modules/@typescript-eslint/parser": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.11.0.tgz", + "integrity": "sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==", + "dependencies": { + "@typescript-eslint/scope-manager": "8.11.0", + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/typescript-estree": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.11.0.tgz", + "integrity": "sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.2.0.tgz", + "integrity": "sha512-g1CfXGFMQdT5S+0PSO0fvGXUaiSkl73U1n9LTK5aRAFnPlJ8dLKkXr4AaLFvPedW8lVDoMgLLE3JN98ZZfsj0w==", "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" + "@typescript-eslint/typescript-estree": "8.2.0", + "@typescript-eslint/utils": "8.2.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", + "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", "engines": { - "node": ">=0.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.2.0.tgz", + "integrity": "sha512-kiG4EDUT4dImplOsbh47B1QnNmXSoUqOjWDvCJw/o8LgfD0yr7k2uy54D5Wm0j4t71Ge1NkynGhpWdS0dEIAUA==", "dependencies": { - "safer-buffer": "~2.1.0" + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0", + "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" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "dev": true, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", + "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", "dependencies": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" + "@typescript-eslint/types": "8.2.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=0.8" + "node": ">=10" } }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, + "node_modules/@typescript-eslint/types": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.11.0.tgz", + "integrity": "sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==", "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.11.0.tgz", + "integrity": "sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==", "dependencies": { - "tslib": "^2.0.1" + "@typescript-eslint/types": "8.11.0", + "@typescript-eslint/visitor-keys": "8.11.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" - }, - "node_modules/async-hook-jl": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", - "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", - "dependencies": { - "stack-chain": "^1.3.7" + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^4.7 || >=6.9 || >=7.3" + "node": ">=10" } }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "node_modules/@typescript-eslint/utils": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.2.0.tgz", + "integrity": "sha512-O46eaYKDlV3TvAVDNcoDzd5N550ckSe8G4phko++OCSC1dYIb9LTc3HDGYdWqWIAT5qDUKphO6sd9RrpIJJPfg==", "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/auto-bind": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", - "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", - "dev": true, + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.2.0", + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/typescript-estree": "8.2.0" + }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/autolinker": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", - "integrity": "sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==", - "dependencies": { - "gulp-header": "^1.7.1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.2.0.tgz", + "integrity": "sha512-OFn80B38yD6WwpoHU2Tz/fTz7CgFqInllBoC3WP+/jLbTb4gGPTy9HBSTsbDWkMdN55XlVU0mMDYAtgvlUspGw==", "dependencies": { - "possible-typed-array-names": "^1.0.0" + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.2.0.tgz", + "integrity": "sha512-6a9QSK396YqmiBKPkJtxsgZZZVjYQ6wQ/TlI0C65z7vInaETuC6HAHD98AGLC8DyIPqHytvNuS8bBVvNLKyqvQ==", "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.2.0.tgz", + "integrity": "sha512-kiG4EDUT4dImplOsbh47B1QnNmXSoUqOjWDvCJw/o8LgfD0yr7k2uy54D5Wm0j4t71Ge1NkynGhpWdS0dEIAUA==", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "@typescript-eslint/types": "8.2.0", + "@typescript-eslint/visitor-keys": "8.2.0", + "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" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.2.0.tgz", + "integrity": "sha512-sbgsPMW9yLvS7IhCi8IpuK1oBmtbWUNP+hBdwl/I9nzqVsszGnNGti5r9dUtF5RLivHUFFIdRvLiTsPhzSyJ3Q==", "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" + "@typescript-eslint/types": "8.2.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=10", - "npm": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, - "node_modules/babel-plugin-macros/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.11.0.tgz", + "integrity": "sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==", + "dependencies": { + "@typescript-eslint/types": "8.11.0", + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">= 6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-plugin-syntax-trailing-function-commas": { - "version": "7.0.0-beta.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", - "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==", - "dev": true - }, - "node_modules/babel-preset-fbjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", - "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", + "node_modules/@vitest/coverage-v8": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.3.tgz", + "integrity": "sha512-2OJ3c7UPoFSmBZwqD2VEkUw6A/tzPF0LmW0ZZhhB8PFxuc+9IBG/FaSM+RLEenc7ljzFvGN+G0nGQoZnh7sy2A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-class-properties": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-member-expression-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-property-literals": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" + "@ampproject/remapping": "^2.3.0", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.6", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magic-string": "^0.30.11", + "magicast": "^0.3.4", + "std-env": "^3.7.0", + "test-exclude": "^7.0.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@vitest/browser": "2.1.3", + "vitest": "2.1.3" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "node_modules/@vitest/expect": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.3.tgz", + "integrity": "sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "node_modules/@vitest/mocker": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.3.tgz", + "integrity": "sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.3", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.11" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/spy": "2.1.3", + "msw": "^2.3.5", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "vite": { + "optional": true } - ] + } }, - "node_modules/basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "node_modules/@vitest/pretty-format": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.3.tgz", + "integrity": "sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==", + "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "5.1.2" + "tinyrainbow": "^1.2.0" }, - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/basic-auth/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "engines": { - "node": ">=10.0.0" + "node_modules/@vitest/runner": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.3.tgz", + "integrity": "sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.3", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "node_modules/@vitest/snapshot": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.3.tgz", + "integrity": "sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==", + "dev": true, + "license": "MIT", "dependencies": { - "tweetnacl": "^0.14.3" + "@vitest/pretty-format": "2.1.3", + "magic-string": "^0.30.11", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + "node_modules/@vitest/spy": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.3.tgz", + "integrity": "sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" + "node_modules/@vitest/utils": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.3.tgz", + "integrity": "sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.3", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/vitest" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@whatwg-node/events": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", + "integrity": "sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==", + "dev": true + }, + "node_modules/@whatwg-node/fetch": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.8.8.tgz", + "integrity": "sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==", "dev": true, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "@peculiar/webcrypto": "^1.4.0", + "@whatwg-node/node-fetch": "^0.3.6", + "busboy": "^1.6.0", + "urlpattern-polyfill": "^8.0.0", + "web-streams-polyfill": "^3.2.1" } }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/@whatwg-node/node-fetch": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz", + "integrity": "sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==", "dev": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "@whatwg-node/events": "^0.0.3", + "busboy": "^1.6.0", + "fast-querystring": "^1.1.1", + "fast-url-parser": "^1.1.3", + "tslib": "^2.3.1" } }, - "node_modules/blessed": { - "version": "0.1.81", - "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", - "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", - "bin": { - "blessed": "bin/tput.js" + "node_modules/@whatwg-node/server": { + "version": "0.9.34", + "resolved": "https://registry.npmjs.org/@whatwg-node/server/-/server-0.9.34.tgz", + "integrity": "sha512-1sHRjqUtZIyTR2m2dS/dJpzS5OcNDpPuUSVDa2PoEgzYVKr4GsqJaYtRaEXXFohvvyh6PkouYCc1rE7jMDWVCA==", + "dependencies": { + "@whatwg-node/fetch": "^0.9.17", + "tslib": "^2.3.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=16.0.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/bodec": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", - "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" + "node_modules/@whatwg-node/server/node_modules/@whatwg-node/events": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", + "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "node_modules/@whatwg-node/server/node_modules/@whatwg-node/fetch": { + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=16.0.0" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@whatwg-node/server/node_modules/@whatwg-node/node-fetch": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dependencies": { - "ms": "2.0.0" + "@kamilkisiela/fast-url-parser": "^1.1.4", + "@whatwg-node/events": "^0.1.0", + "busboy": "^1.6.0", + "fast-querystring": "^1.1.1", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + "node_modules/@whatwg-node/server/node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "balanced-match": "^1.0.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "dependencies": { - "fill-range": "^7.1.1" + "debug": "^4.3.4" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/braces/node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, + "node_modules/amp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", + "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==" + }, + "node_modules/amp-message": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", + "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==", "dependencies": { - "node-int64": "^0.4.0" + "amp": "0.3.1" } }, - "node_modules/bson": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz", - "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==", + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "engines": { - "node": ">=16.20.1" + "node": ">=6" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { - "streamsearch": "^1.1.0" + "type-fest": "^0.21.3" }, "engines": { - "node": ">=10.16.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==", + "dependencies": { + "ansi-wrap": "0.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001600", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", - "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } }, - "node_modules/chai": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", - "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" + "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" }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/change-case-all": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz", - "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "dependencies": { - "change-case": "^4.1.2", - "is-lower-case": "^2.0.2", - "is-upper-case": "^2.0.2", - "lower-case": "^2.0.2", - "lower-case-first": "^2.0.2", - "sponge-case": "^1.0.1", - "swap-case": "^2.0.2", - "title-case": "^3.0.3", - "upper-case": "^2.0.2", - "upper-case-first": "^2.0.2" + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, - "node_modules/charm": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", - "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", "dev": true, + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, "engines": { - "node": ">= 16" + "node": ">=12.0.0" } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=0.8" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dependencies": { - "is-glob": "^4.0.1" + "tslib": "^2.0.1" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/async-hook-jl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz", + "integrity": "sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg==", "dependencies": { - "restore-cursor": "^3.1.0" + "stack-chain": "^1.3.7" }, "engines": { - "node": ">=8" + "node": "^4.7 || >=6.9 || >=7.3" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dependencies": { + "retry": "0.13.1" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/auto-bind": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", + "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "node_modules/autolinker": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.28.1.tgz", + "integrity": "sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==", "dependencies": { - "string-width": "^4.2.0" + "gulp-header": "^1.7.1" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": "10.* || >= 12.*" + "node": ">= 0.4" }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cli-tableau": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", - "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", - "dependencies": { - "chalk": "3.0.0" - }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "engines": { - "node": ">=8.10.0" + "node": "*" } }, - "node_modules/cli-tableau/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" }, "engines": { - "node": ">=8" + "node": ">=10", + "npm": ">=6" } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, + "node_modules/babel-plugin-macros/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { - "node": ">= 10" + "node": ">= 6" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/babel-plugin-syntax-trailing-function-commas": { + "version": "7.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", + "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==", + "dev": true + }, + "node_modules/babel-preset-fbjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", + "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", + "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-syntax-class-properties": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-block-scoped-functions": "^7.0.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.0.0", + "@babel/plugin-transform-flow-strip-types": "^7.0.0", + "@babel/plugin-transform-for-of": "^7.0.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-member-expression-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-object-super": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-property-literals": "^7.0.0", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-template-literals": "^7.0.0", + "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "safe-buffer": "5.1.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", "engines": { - "node": ">=0.8" + "node": ">=10.0.0" } }, - "node_modules/cls-bluebird": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", - "integrity": "sha512-XVb0RPmHQyy35Tz9z34gvtUcBKUK8A/1xkGCyeFc9B0C7Zr5SysgFaswRVdwI5NEMcO+3JKlIDGIOgERSn9NdA==", - "dev": true, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dependencies": { - "is-bluebird": "^1.0.2", - "shimmer": "^1.1.0" + "tweetnacl": "^0.14.3" } }, - "node_modules/cls-hooked": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", - "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", - "dependencies": { - "async-hook-jl": "^1.7.6", - "emitter-listener": "^1.0.1", - "semver": "^5.4.1" - }, - "engines": { - "node": "^4.7 || >=6.9 || >=7.3 || >=8.2.1" - } + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" }, - "node_modules/cls-hooked/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "engines": { - "node": ">=6" + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/coffee-script": { - "version": "1.12.7", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", - "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", - "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "node_modules/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", "bin": { - "cake": "bin/cake", - "coffee": "bin/coffee" + "blessed": "bin/tput.js" }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.8.0" } }, - "node_modules/color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { - "color-name": "~1.1.4" + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "ms": "2.0.0" } }, - "node_modules/color/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, - "node_modules/colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" + "balanced-match": "^1.0.0" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "delayed-stream": "~1.0.0" + "fill-range": "^7.1.1" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, + "node_modules/braces/node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/commonmark": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.30.0.tgz", - "integrity": "sha512-j1yoUo4gxPND1JWV9xj5ELih0yMv1iCWDG6eEQIPLSWLxzCXiFoyS7kvB+WwU+tZMf4snwJMMtaubV0laFpiBA==", + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "entities": "~2.0", - "mdurl": "~1.0.1", - "minimist": ">=1.2.2", - "string.prototype.repeat": "^0.2.0" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { - "commonmark": "bin/commonmark" + "browserslist": "cli.js" }, "engines": { - "node": "*" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "node-int64": "^0.4.0" } }, - "node_modules/concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "node_modules/bson": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz", + "integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "source-map": "^0.6.1" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/concat-with-sourcemaps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, - "node_modules/concurrently": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.0.0.tgz", - "integrity": "sha512-iAxbsDeUkn8E/4+QalT7T3WvlyTfmsoez+19lbbcsxZdOEMfBukd8LA30KYez2UR5xkKFzbcqXIZy5RisCbaxw==", - "dev": true, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { - "chalk": "^4.1.2", - "lodash": "^4.17.21", - "rxjs": "^7.8.1", - "shell-quote": "^1.8.1", - "supports-color": "^8.1.1", - "tree-kill": "^1.2.2", - "yargs": "^17.7.2" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" + "streamsearch": "^1.1.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + "node": ">=10.16.0" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "safe-buffer": "5.2.1" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "node_modules/caniuse-lite": { + "version": "1.0.30001600", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001600.tgz", + "integrity": "sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] }, - "node_modules/copy-paste": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/copy-paste/-/copy-paste-1.5.3.tgz", - "integrity": "sha512-qOnFo+8l8vemGmdcoCiD7gPTefkXEg2rivYE+EBtuKOj754eFivkGhGAM9e/xqShrpuVE11evSxGnHwVAUK1Iw==", + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, "dependencies": { - "iconv-lite": "^0.4.8" + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/chai": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", + "dev": true, + "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=12" } }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/croner": { - "version": "4.1.97", - "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", - "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" - }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", - "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz", + "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==", "dev": true, "dependencies": { - "node-fetch": "^2.6.12" + "change-case": "^4.1.2", + "is-lower-case": "^2.0.2", + "is-upper-case": "^2.0.2", + "lower-case": "^2.0.2", + "lower-case-first": "^2.0.2", + "sponge-case": "^1.0.1", + "swap-case": "^2.0.2", + "title-case": "^3.0.3", + "upper-case": "^2.0.2", + "upper-case-first": "^2.0.2" } }, - "node_modules/cross-inspect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.0.tgz", - "integrity": "sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==", - "dependencies": { - "tslib": "^2.4.0" - }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=16.0.0" + "node": ">= 16" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">= 8" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/culvert": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", - "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "assert-plus": "^1.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=0.10" + "node": ">= 6" } }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, "engines": { - "node": ">= 14" + "node": ">=6" } }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "string-width": "^4.2.0" }, "engines": { - "node": ">= 0.4" + "node": "10.* || >= 12.*" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/dataloader": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", - "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" - }, - "node_modules/date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "node_modules/cli-tableau": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", + "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", + "dependencies": { + "chalk": "3.0.0" + }, + "engines": { + "node": ">=8.10.0" } }, - "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "node_modules/cli-tableau/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dependencies": { - "ms": "2.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=8" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-diff": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", - "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, "engines": { - "node": ">=6" + "node": ">= 10" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { - "clone": "^1.0.2" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=12" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=0.8" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha512-XVb0RPmHQyy35Tz9z34gvtUcBKUK8A/1xkGCyeFc9B0C7Zr5SysgFaswRVdwI5NEMcO+3JKlIDGIOgERSn9NdA==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" } }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "node_modules/cls-hooked": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz", + "integrity": "sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw==", "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" + "async-hook-jl": "^1.7.6", + "emitter-listener": "^1.0.1", + "semver": "^5.4.1" }, "engines": { - "node": ">= 14" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" + "node": "^4.7 || >=6.9 || >=7.3 || >=8.2.1" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" + "node_modules/cls-hooked/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "dev": true, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "engines": { - "node": ">= 0.6.0" + "node": ">=0.10.0" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=0.8.0" } }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "dev": true, - "bin": { - "detect-libc": "bin/detect-libc.js" + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10" + "node": ">=7.0.0" } }, - "node_modules/diacritics-map": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", - "integrity": "sha512-3omnDTYrGigU0i4cJjvaKwD52B8aoqyX/NEIkukFFkogBemsIbhSa1O414fpTp5nuszJG6lvQ5vBvDVNCbSsaQ==", - "engines": { - "node": ">=0.8.0" + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" + "color-name": "1.1.3" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" + "color": "^3.1.3", + "text-hex": "1.0.x" } }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "engines": { + "node": ">=18" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=4.0.0" } }, - "node_modules/dset": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", - "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", + "node_modules/commonmark": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.30.0.tgz", + "integrity": "sha512-j1yoUo4gxPND1JWV9xj5ELih0yMv1iCWDG6eEQIPLSWLxzCXiFoyS7kvB+WwU+tZMf4snwJMMtaubV0laFpiBA==", + "dependencies": { + "entities": "~2.0", + "mdurl": "~1.0.1", + "minimist": ">=1.2.2", + "string.prototype.repeat": "^0.2.0" + }, + "bin": { + "commonmark": "bin/commonmark" + }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ecc-jsbn/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], "dependencies": { - "safe-buffer": "^5.0.1" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.715", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", - "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==" - }, - "node_modules/emitter-listener": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", - "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dependencies": { - "shimmer": "^1.2.0" + "source-map": "^0.6.1" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/concat-with-sourcemaps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/concurrently": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.0.1.tgz", + "integrity": "sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==", + "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" }, "engines": { - "node": ">=8.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" } }, - "node_modules/es-abstract": { - "version": "1.23.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", - "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", - "dev": true, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "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.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "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.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.7", - "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.5", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "safe-buffer": "5.2.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "node_modules/copy-paste": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/copy-paste/-/copy-paste-1.5.3.tgz", + "integrity": "sha512-qOnFo+8l8vemGmdcoCiD7gPTefkXEg2rivYE+EBtuKOj754eFivkGhGAM9e/xqShrpuVE11evSxGnHwVAUK1Iw==", "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" + "iconv-lite": "^0.4.8" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" + "node": ">= 0.10" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "url": "https://github.com/sponsors/d-fischer" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "typescript": ">=4.9.5" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" + "cross-spawn": "^7.0.1" }, "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" }, "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "engines": { - "node": ">=0.10.0" + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dev": true, + "dependencies": { + "node-fetch": "^2.6.12" } }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "node_modules/cross-inspect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.0.tgz", + "integrity": "sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@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", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" + "tslib": "^2.4.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=16.0.0" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": ">= 8" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "node_modules/culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dependencies": { - "ms": "^2.1.1" + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, "dependencies": { - "debug": "^3.2.7" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, "dependencies": { - "ms": "^2.1.1" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/dataloader": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { - "ms": "^2.1.1" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/deep-diff": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", + "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.3.0.tgz", - "integrity": "sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "dependencies": { - "@microsoft/tsdoc": "0.15.0", - "@microsoft/tsdoc-config": "0.17.0" + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=8" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "dependencies": { - "brace-expansion": "^1.1.7" + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" }, "engines": { - "node": "*" + "node": ">= 14" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "detect-libc": "bin/detect-libc.js" }, "engines": { - "node": ">=4" + "node": ">=0.10" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "dependencies": { - "estraverse": "^5.1.0" - }, + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diacritics-map": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/diacritics-map/-/diacritics-map-0.1.0.tgz", + "integrity": "sha512-3omnDTYrGigU0i4cJjvaKwD52B8aoqyX/NEIkukFFkogBemsIbhSa1O414fpTp5nuszJG6lvQ5vBvDVNCbSsaQ==", "engines": { - "node": ">=0.10" + "node": ">=0.8.0" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dependencies": { - "estraverse": "^5.2.0" + "path-type": "^4.0.0" }, "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" } }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dev": true, "dependencies": { - "@types/estree": "^1.0.0" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/dset": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/eventemitter2": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", - "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==" - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", - "dependencies": { - "fill-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" + "safe-buffer": "^5.0.1" } }, - "node_modules/express-mongo-sanitize": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/express-mongo-sanitize/-/express-mongo-sanitize-2.2.0.tgz", - "integrity": "sha512-PZBs5nwhD6ek9ZuP+W2xmpvcrHwXZxD5GdieX2dsjPbAbH4azOkrHbycBud2QRU+YQF1CT+pki/lZGedHgo/dQ==", - "engines": { - "node": ">=10" - } + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, - "node_modules/express-rate-limit": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.0.tgz", - "integrity": "sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": "4 || 5 || ^5.0.0-beta.1" - } + "node_modules/electron-to-chromium": { + "version": "1.4.715", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.715.tgz", + "integrity": "sha512-XzWNH4ZSa9BwVUQSDorPWAUQ5WGuYz7zJUNpNif40zFCiCl20t8zgylmreNmn26h5kiyw2lg7RfTmeMBsDklqg==" }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", "dependencies": { - "ms": "2.0.0" + "shimmer": "^1.2.0" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "ansi-colors": "^4.1.1" }, "engines": { - "node": ">=4" + "node": ">=8.6" } }, - "node_modules/extract-files": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", - "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", + "node_modules/entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, "engines": { - "node": "^12.20 || >= 14.13" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/jaydenseric" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extrareqp2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", - "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dependencies": { - "follow-redirects": "^1.14.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "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.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "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.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.7", + "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.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { - "node": ">=8.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dependencies": { - "is-glob": "^4.0.1" + "get-intrinsic": "^1.2.4" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" } }, - "node_modules/fast-json-patch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/fast-printf": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", - "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, "dependencies": { - "boolean": "^3.1.4" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=10.0" + "node": ">= 0.4" } }, - "node_modules/fast-querystring": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", - "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, "dependencies": { - "fast-decode-uri-component": "^1.0.1" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "punycode": "^1.3.2" + "hasown": "^2.0.0" } }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "dependencies": { - "reusify": "^1.0.4" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", + "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.1", + "@esbuild/android-arm": "0.23.1", + "@esbuild/android-arm64": "0.23.1", + "@esbuild/android-x64": "0.23.1", + "@esbuild/darwin-arm64": "0.23.1", + "@esbuild/darwin-x64": "0.23.1", + "@esbuild/freebsd-arm64": "0.23.1", + "@esbuild/freebsd-x64": "0.23.1", + "@esbuild/linux-arm": "0.23.1", + "@esbuild/linux-arm64": "0.23.1", + "@esbuild/linux-ia32": "0.23.1", + "@esbuild/linux-loong64": "0.23.1", + "@esbuild/linux-mips64el": "0.23.1", + "@esbuild/linux-ppc64": "0.23.1", + "@esbuild/linux-riscv64": "0.23.1", + "@esbuild/linux-s390x": "0.23.1", + "@esbuild/linux-x64": "0.23.1", + "@esbuild/netbsd-x64": "0.23.1", + "@esbuild/openbsd-arm64": "0.23.1", + "@esbuild/openbsd-x64": "0.23.1", + "@esbuild/sunos-x64": "0.23.1", + "@esbuild/win32-arm64": "0.23.1", + "@esbuild/win32-ia32": "0.23.1", + "@esbuild/win32-x64": "0.23.1" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/esbuild/node_modules/@esbuild/aix-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", + "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "bser": "2.1.1" + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" } }, - "node_modules/fbjs": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", - "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", + "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "cross-fetch": "^3.1.5", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^1.0.35" - } - }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", - "dev": true - }, - "node_modules/fclone": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", - "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" - }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", + "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.8.0" + "node": ">=18" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dependencies": { - "flat-cache": "^3.0.4" - }, + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", + "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=18" } }, - "node_modules/file-type": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", - "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", - "dependencies": { - "readable-web-to-node-stream": "^3.0.0", - "strtok3": "^6.2.4", - "token-types": "^4.1.1" - }, + "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", + "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" + "node": ">=18" } }, - "node_modules/fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dependencies": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - }, + "node_modules/esbuild/node_modules/@esbuild/darwin-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", + "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", + "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", + "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", + "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", + "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=18" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", + "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" - }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } + "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", + "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" ], "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node": ">=18" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", + "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "is-callable": "^1.1.3" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", + "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", + "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=18" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", + "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 6" + "node": ">=18" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", + "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 0.6" + "node": ">=18" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", + "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.6" + "node": ">=18" } }, - "node_modules/fs-capacitor": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-8.0.0.tgz", - "integrity": "sha512-+Lk6iSKajdGw+7XYxUkwIzreJ2G1JFlYOdnKJv5PzwFLVsoJYBpCuS7WPIUSNT1IbQaEWT1nhYU63Ud03DyzLA==", + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", + "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", + "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14.14" + "node": ">=18" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", + "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ - "darwin" + "win32" ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=18" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, "engines": { - "node": ">= 4" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "node_modules/eslint": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", + "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.10.0", + "@eslint/plugin-kit": "^0.1.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "engines": { - "node": ">=18" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/get-graphql-schema": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/get-graphql-schema/-/get-graphql-schema-2.1.2.tgz", - "integrity": "sha512-1z5Hw91VrE3GrpCZE6lE8Dy+jz4kXWesLS7rCSjwOxf5BOcIedAZeTUJRIeIzmmR+PA9CKOkPTYFRJbdgUtrxA==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "chalk": "^2.4.1", - "graphql": "^14.0.2", - "minimist": "^1.2.0", - "node-fetch": "^2.2.0" - }, - "bin": { - "get-graphql-schema": "dist/index.js" + "ms": "^2.1.1" } }, - "node_modules/get-graphql-schema/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/get-graphql-schema/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" + "ms": "^2.1.1" } }, - "node_modules/get-graphql-schema/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/get-graphql-schema/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/get-graphql-schema/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "engines": { - "node": ">=0.8.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/get-graphql-schema/node_modules/graphql": { - "version": "14.7.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", - "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "iterall": "^1.2.2" - }, - "engines": { - "node": ">= 6.x" + "ms": "^2.1.1" } }, - "node_modules/get-graphql-schema/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/get-graphql-schema/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/eslint-plugin-tsdoc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.3.0.tgz", + "integrity": "sha512-0MuFdBrrJVBjT/gyhkP2BqpD0np1NxNLfQ38xXDlSs/KVVpKI2A6vN7jx2Rve/CyUsvOsMGwp9KKrinv7q9g3A==", + "dev": true, "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "@microsoft/tsdoc": "0.15.0", + "@microsoft/tsdoc-config": "0.17.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "engines": { - "node": ">=16" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, + "node_modules/eslint/node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", - "dev": true, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.10.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", + "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/get-uri": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", - "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "node_modules/eslint/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4", - "fs-extra": "^11.2.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 14" + "node": "*" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "license": "BSD-2-Clause", "dependencies": { - "assert-plus": "^1.0.0" + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/git-node-fs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", - "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==" + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - "node_modules/git-sha1": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", - "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==" + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "estraverse": "^5.1.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", "dependencies": { - "is-glob": "^4.0.3" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=4.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@types/estree": "^1.0.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==" + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", + "dependencies": { + "fill-range": "^2.1.0" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { - "define-properties": "^1.1.3" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.10.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, + "node_modules/express-mongo-sanitize": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/express-mongo-sanitize/-/express-mongo-sanitize-2.2.0.tgz", + "integrity": "sha512-PZBs5nwhD6ek9ZuP+W2xmpvcrHwXZxD5GdieX2dsjPbAbH4azOkrHbycBud2QRU+YQF1CT+pki/lZGedHgo/dQ==", "engines": { "node": ">=10" + } + }, + "node_modules/express-rate-limit": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.1.tgz", + "integrity": "sha512-KS3efpnpIDVIXopMc65EMbWbUht7qvTCdtCR2dD/IZmi9MIkopYESwyRqLgv8Pfu589+KqDqOdzJWW7AHoACeg==", + "license": "MIT", + "engines": { + "node": ">= 16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "4 || 5 || ^5.0.0-beta.1" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "2.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "node_modules/graphql": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", - "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", - "license": "MIT", + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + "node": ">=0.10.0" } }, - "node_modules/graphql-config": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.0.3.tgz", - "integrity": "sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ==", + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "dependencies": { - "@graphql-tools/graphql-file-loader": "^8.0.0", - "@graphql-tools/json-file-loader": "^8.0.0", - "@graphql-tools/load": "^8.0.0", - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/url-loader": "^8.0.0", - "@graphql-tools/utils": "^10.0.0", - "cosmiconfig": "^8.1.0", - "jiti": "^1.18.2", - "minimatch": "^4.2.3", - "string-env-interpolation": "^1.0.1", - "tslib": "^2.4.0" + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" }, "engines": { - "node": ">= 16.0.0" - }, - "peerDependencies": { - "cosmiconfig-toml-loader": "^1.0.0", - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "node": ">=4" + } + }, + "node_modules/extract-files": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", + "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", + "engines": { + "node": "^12.20 || >= 14.13" }, - "peerDependenciesMeta": { - "cosmiconfig-toml-loader": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/jaydenseric" } }, - "node_modules/graphql-config/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "node_modules/extrareqp2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", + "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "follow-redirects": "^1.14.0" } }, - "node_modules/graphql-config/node_modules/minimatch": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.3.tgz", - "integrity": "sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==", - "dev": true, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { - "brace-expansion": "^1.1.7" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=10" + "node": ">=8.6.0" } }, - "node_modules/graphql-depth-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/graphql-depth-limit/-/graphql-depth-limit-1.1.0.tgz", - "integrity": "sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "arrify": "^1.0.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "graphql": "*" + "node": ">= 6" } }, - "node_modules/graphql-markdown": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/graphql-markdown/-/graphql-markdown-7.1.0.tgz", - "integrity": "sha512-S7wff3Fy5deUSfGB7J+IYO3mygulQQSpHoSnhq3GlD6q/oYGuCfRyuQqCivtHI0yHnPVM33c/VGF7pbCzvsNJg==", - "dev": true, - "dependencies": { - "deep-diff": "^1.0.2", - "lodash.isplainobject": "^4.0.6", - "minimist": "^1.2.6", - "node-fetch": "^2.0.0", - "resolve-from": "^5.0.0" - }, - "bin": { - "graphql-markdown": "src/index.js" + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.2 || ^15.0.0 || ^16.0.0" + "node": ">=10.0" } }, - "node_modules/graphql-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", - "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", - "dev": true, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", "dependencies": { - "@graphql-typed-document-node/core": "^3.2.0", - "cross-fetch": "^3.1.5" - }, - "peerDependencies": { - "graphql": "14 - 16" + "fast-decode-uri-component": "^1.0.1" } }, - "node_modules/graphql-scalars": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/graphql-scalars/-/graphql-scalars-1.23.0.tgz", - "integrity": "sha512-YTRNcwitkn8CqYcleKOx9IvedA8JIERn8BRq21nlKgOr4NEcTaWEG0sT+H92eF3ALTFbPgsqfft4cw+MGgv0Gg==", + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dev": true, "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "punycode": "^1.3.2" } }, - "node_modules/graphql-subscriptions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-2.0.0.tgz", - "integrity": "sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==", + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], "dependencies": { - "iterall": "^1.3.0" + "strnum": "^1.0.5" }, - "peerDependencies": { - "graphql": "^15.7.2 || ^16.0.0" + "bin": { + "fxparser": "src/cli/cli.js" } }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + "reusify": "^1.0.4" } }, - "node_modules/graphql-upload": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-16.0.2.tgz", - "integrity": "sha512-enwIkZqUELdNH9lrjHlTNfj7gLitSa0EAX4TNXZtg2frnmQzPhpjH0l+6K7ft274fhoRCIcz8SKiNRJDf/cG4Q==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, "dependencies": { - "@types/busboy": "^1.5.0", - "@types/node": "*", - "@types/object-path": "^0.11.1", - "busboy": "^1.6.0", - "fs-capacitor": "^8.0.0", - "http-errors": "^2.0.0", - "object-path": "^0.11.8" - }, - "engines": { - "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/jaydenseric" - }, - "peerDependencies": { - "@types/express": "^4.0.29", - "@types/koa": "^2.11.4", - "graphql": "^16.3.0" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - }, - "@types/koa": { - "optional": true - } + "bser": "2.1.1" } }, - "node_modules/graphql-voyager": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/graphql-voyager/-/graphql-voyager-2.0.0.tgz", - "integrity": "sha512-mlLUChRP1k6chHCfOMBBfnvuDnMrEQho0EYzuBhBV7oIZJPh97FqTAaly4jpUAMOFxSR5SBDpNLy0cLesHG9sg==", - "dependencies": { - "@emotion/react": "11.10.5", - "@emotion/styled": "11.10.5", - "@mui/icons-material": "5.11.0", - "@mui/lab": "5.0.0-alpha.114", - "@mui/material": "5.11.2", - "commonmark": "0.30.0", - "svg-pan-zoom": "3.6.1" - }, - "funding": { - "url": "https://github.com/graphql-kit/graphql-voyager?sponsor=1" - }, - "peerDependencies": { - "graphql": ">=16.5.0", - "react": ">=18.0.0" + "node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "dev": true, + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" } }, - "node_modules/graphql-ws": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", - "integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": ">=0.11 <=16" - } + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "dev": true }, - "node_modules/graphql-yoga": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/graphql-yoga/-/graphql-yoga-5.3.1.tgz", - "integrity": "sha512-n918QV6TF7xTjb9ASnozgsr4ydMc08c+x4eRAWKxxWVwSnzdP2xeN2zw1ljIzRD0ccSCNoBajGDKwcZkJDitPA==", + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dependencies": { - "@envelop/core": "^5.0.0", - "@graphql-tools/executor": "^1.2.5", - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.1.0", - "@graphql-yoga/logger": "^2.0.0", - "@graphql-yoga/subscription": "^5.0.0", - "@whatwg-node/fetch": "^0.9.17", - "@whatwg-node/server": "^0.9.33", - "dset": "^3.1.1", - "lru-cache": "^10.0.0", - "tslib": "^2.5.2" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=18.0.0" + "node": ">=8" }, - "peerDependencies": { - "graphql": "^15.2.0 || ^16.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graphql-yoga/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=16.0.0" + "node": ">=0.8.0" } }, - "node_modules/graphql-yoga/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" + "flat-cache": "^4.0.0" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/graphql-yoga/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" }, "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/graphql-yoga/node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "engines": { - "node": "14 || >=16.14" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/graphql-yoga/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" - }, - "node_modules/gray-matter": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", - "integrity": "sha512-vbmvP1Fe/fxuT2QuLVcqb2BfK7upGhhbLIt9/owWEvPYrZZEkelLcq2HqzxosV+PQ67dUFLaAeNpH7C4hhICAA==", + "node_modules/fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dependencies": { - "ansi-red": "^0.1.1", - "coffee-script": "^1.12.4", - "extend-shallow": "^2.0.1", - "js-yaml": "^3.8.1", - "toml": "^2.3.2" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gray-matter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 0.8" } }, - "node_modules/gray-matter/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/gulp-header": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", - "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", - "deprecated": "Removed event-stream from gulp-header", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "concat-with-sourcemaps": "*", - "lodash.template": "^4.4.0", - "through2": "^2.0.0" + "ms": "2.0.0" } }, - "node_modules/har-schema": { + "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": ">=6" + "node": ">=16" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "license": "ISC" + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "is-callable": "^1.1.3" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, "dependencies": { - "es-define-property": "^1.0.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { - "has-symbols": "^1.0.3" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/formidable": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz", + "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==", + "dev": true, "dependencies": { - "function-bind": "^1.1.2" + "dezalgo": "^1.0.4", + "hexoid": "^2.0.0", + "once": "^1.4.0" }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/helmet": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", - "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "node_modules/fs-capacitor": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-8.0.0.tgz", + "integrity": "sha512-+Lk6iSKajdGw+7XYxUkwIzreJ2G1JFlYOdnKJv5PzwFLVsoJYBpCuS7WPIUSNT1IbQaEWT1nhYU63Ud03DyzLA==", "engines": { - "node": ">=16.0.0" + "node": "^14.17.0 || >=16.0.0" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dependencies": { - "react-is": "^16.7.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" + "node": ">= 4" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "engines": { - "node": ">= 14" + "node": ">=6.9.0" } }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "engines": { - "node": ">=16.17.0" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/husky": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.5.tgz", - "integrity": "sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==", + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, - "bin": { - "husky": "bin.js" - }, "engines": { "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/typicode" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/i18n": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", - "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", + "node_modules/get-graphql-schema": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/get-graphql-schema/-/get-graphql-schema-2.1.2.tgz", + "integrity": "sha512-1z5Hw91VrE3GrpCZE6lE8Dy+jz4kXWesLS7rCSjwOxf5BOcIedAZeTUJRIeIzmmR+PA9CKOkPTYFRJbdgUtrxA==", + "dev": true, "dependencies": { - "@messageformat/core": "^3.0.0", - "debug": "^4.3.3", - "fast-printf": "^1.6.9", - "make-plural": "^7.0.0", - "math-interval-parser": "^2.0.1", - "mustache": "^4.2.0" - }, - "engines": { - "node": ">=10" + "chalk": "^2.4.1", + "graphql": "^14.0.2", + "minimist": "^1.2.0", + "node-fetch": "^2.2.0" }, - "funding": { - "url": "https://github.com/sponsors/mashpie" + "bin": { + "get-graphql-schema": "dist/index.js" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/get-graphql-schema/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "node_modules/get-graphql-schema/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">= 4" + "node": ">=4" } }, - "node_modules/image-hash": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/image-hash/-/image-hash-5.3.2.tgz", - "integrity": "sha512-of8SekDXKFoaK4R93dP/Lzw6+NRGag8Jr9YlIIZ9jJVn9KYLfYVo/ARbKtbRn+tdTz/wDzBObx6yflKpLSYbxA==", + "node_modules/get-graphql-schema/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { - "@cwasm/webp": "^0.1.5", - "file-type": "^16.5.3", - "jpeg-js": "^0.4.0", - "pngjs": "^6.0.0", - "request": "^2.81.0" + "color-name": "1.1.3" } }, - "node_modules/immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==", + "node_modules/get-graphql-schema/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/get-graphql-schema/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { "node": ">=0.8.0" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/get-graphql-schema/node_modules/graphql": { + "version": "14.7.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", + "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", + "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" + "iterall": "^1.2.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", - "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", - "dev": true, "engines": { - "node": ">=12.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6.x" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/get-graphql-schema/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { - "node": ">=0.8.19" + "node": ">=4" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/get-graphql-schema/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, "engines": { - "node": ">=12.0.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { + "call-bind": "^1.0.5", "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", "dev": true, "dependencies": { - "loose-envify": "^1.0.0" + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/ioredis": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", - "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "node_modules/get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", "dependencies": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", "debug": "^4.3.4", - "denque": "^2.1.0", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" + "fs-extra": "^11.2.0" }, "engines": { - "node": ">=12.22.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ioredis" + "node": ">= 14" } }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" + "assert-plus": "^1.0.0" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" + "node_modules/git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==" }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } + "node_modules/git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==" }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.13.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/is-bluebird": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", - "integrity": "sha512-PDRu1vVip5dGQg5tfn2qVCCyxbBYu5MhYUJwSfL/RoGBI97n1fxvilVazxzptZW0gcmsMH17H4EVZZI5E/RSeA==", + "node_modules/globals": { + "version": "15.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", + "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "define-properties": "^1.1.3" }, "engines": { "node": ">= 0.4" @@ -11004,1173 +12080,1237 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "hasown": "^2.0.0" + "get-intrinsic": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-config": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.1.3.tgz", + "integrity": "sha512-RBhejsPjrNSuwtckRlilWzLVt2j8itl74W9Gke1KejDTz7oaA5kVd6wRn9zK9TS5mcmIYGxf7zN7a1ORMdxp1Q==", "dev": true, "dependencies": { - "is-typed-array": "^1.1.13" + "@graphql-tools/graphql-file-loader": "^8.0.0", + "@graphql-tools/json-file-loader": "^8.0.0", + "@graphql-tools/load": "^8.0.0", + "@graphql-tools/merge": "^9.0.0", + "@graphql-tools/url-loader": "^8.0.0", + "@graphql-tools/utils": "^10.0.0", + "cosmiconfig": "^8.1.0", + "jiti": "^2.0.0", + "minimatch": "^9.0.5", + "string-env-interpolation": "^1.0.1", + "tslib": "^2.4.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 16.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "cosmiconfig-toml-loader": "^1.0.0", + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "cosmiconfig-toml-loader": { + "optional": true + } } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/graphql-config/node_modules/jiti": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.0.tgz", + "integrity": "sha512-H5UpaUI+aHOqZXlYOaFP/8AzKsg+guWu+Pr3Y8i7+Y3zr1aXAvCvTAQ1RxSc6oVD8R8c7brgNtTVP91E7upH/g==", "dev": true, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/graphql-depth-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/graphql-depth-limit/-/graphql-depth-limit-1.1.0.tgz", + "integrity": "sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==", "dependencies": { - "has-tostringtag": "^1.0.0" + "arrify": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "graphql": "*" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/graphql-markdown": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/graphql-markdown/-/graphql-markdown-7.3.0.tgz", + "integrity": "sha512-xTgP+W156DD3k55KpwvNUtV7RTJmGKQhvCzseUXSnJf7KrZozhyyxhq4bv1IiOJgGeRjt5zwHBbEcAEEWCacrg==", + "dev": true, + "dependencies": { + "deep-diff": "^1.0.2", + "lodash.isplainobject": "^4.0.6", + "minimist": "^1.2.6", + "node-fetch": "^2.0.0", + "resolve-from": "^5.0.0" + }, "bin": { - "is-docker": "cli.js" + "graphql-markdown": "src/index.js" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "graphql": "^14.0.2 || ^15.0.0 || ^16.0.0" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" + "node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dev": true, + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/graphql-scalars": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/graphql-scalars/-/graphql-scalars-1.23.0.tgz", + "integrity": "sha512-YTRNcwitkn8CqYcleKOx9IvedA8JIERn8BRq21nlKgOr4NEcTaWEG0sT+H92eF3ALTFbPgsqfft4cw+MGgv0Gg==", + "dependencies": { + "tslib": "^2.5.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/graphql-subscriptions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-2.0.0.tgz", + "integrity": "sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==", + "dependencies": { + "iterall": "^1.3.0" + }, + "peerDependencies": { + "graphql": "^15.7.2 || ^16.0.0" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dependencies": { + "tslib": "^2.1.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/graphql-upload": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-17.0.0.tgz", + "integrity": "sha512-AI42S1UR1mdqg+LQ7KqGbrgcf4l9gpPu/R0drM4vSA5C94NfIjYyCeCdpktEledvZoAL8JURLLeB53++WACo1w==", "dependencies": { - "is-extglob": "^2.1.1" + "@types/busboy": "^1.5.0", + "@types/node": "*", + "@types/object-path": "^0.11.1", + "busboy": "^1.6.0", + "fs-capacitor": "^8.0.0", + "http-errors": "^2.0.0", + "object-path": "^0.11.8" }, "engines": { - "node": ">=0.10.0" + "node": "^18.18.0 || ^20.9.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/jaydenseric" + }, + "peerDependencies": { + "@types/express": "4.0.29 - 5", + "@types/koa": "^2.11.4", + "graphql": "^16.3.0" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + }, + "@types/koa": { + "optional": true + } } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, + "node_modules/graphql-voyager": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/graphql-voyager/-/graphql-voyager-2.1.0.tgz", + "integrity": "sha512-CmYqMMK9aNpi7lMf1/9HvIj0Vyc01EokngZPPZgazH8DWWpVOWYt2OQfkzZVWm7ZgyMqMeKOyhNtjVZbOUNB8A==", + "dependencies": { + "@emotion/react": "11.13.3", + "@emotion/styled": "11.13.0", + "@mui/icons-material": "5.16.7", + "@mui/lab": "5.0.0-alpha.169", + "@mui/material": "5.16.7", + "commonmark": "0.30.0", + "svg-pan-zoom": "3.6.1" + }, "engines": { - "node": ">=8" + "node": ">=20.0.0" + }, + "funding": { + "url": "https://github.com/graphql-kit/graphql-voyager?sponsor=1" + }, + "peerDependencies": { + "graphql": ">=16.5.0", + "react": ">=18.0.0" } }, - "node_modules/is-lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", - "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==", - "dev": true, + "node_modules/graphql-ws": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", + "integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/graphql-yoga": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/graphql-yoga/-/graphql-yoga-5.3.1.tgz", + "integrity": "sha512-n918QV6TF7xTjb9ASnozgsr4ydMc08c+x4eRAWKxxWVwSnzdP2xeN2zw1ljIzRD0ccSCNoBajGDKwcZkJDitPA==", "dependencies": { - "tslib": "^2.0.3" + "@envelop/core": "^5.0.0", + "@graphql-tools/executor": "^1.2.5", + "@graphql-tools/schema": "^10.0.0", + "@graphql-tools/utils": "^10.1.0", + "@graphql-yoga/logger": "^2.0.0", + "@graphql-yoga/subscription": "^5.0.0", + "@whatwg-node/fetch": "^0.9.17", + "@whatwg-node/server": "^0.9.33", + "dset": "^3.1.1", + "lru-cache": "^10.0.0", + "tslib": "^2.5.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^15.2.0 || ^16.0.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, + "node_modules/graphql-yoga/node_modules/@whatwg-node/events": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", + "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16.0.0" } }, - "node_modules/is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "node_modules/graphql-yoga/node_modules/@whatwg-node/fetch": { + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dependencies": { - "kind-of": "^3.0.2" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=16.0.0" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, + "node_modules/graphql-yoga/node_modules/@whatwg-node/node-fetch": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dependencies": { - "has-tostringtag": "^1.0.0" + "@kamilkisiela/fast-url-parser": "^1.1.4", + "@whatwg-node/events": "^0.1.0", + "busboy": "^1.6.0", + "fast-querystring": "^1.1.1", + "tslib": "^2.3.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16.0.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/graphql-yoga/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "engines": { - "node": ">=8" + "node": "14 || >=16.14" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/graphql-yoga/node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" + }, + "node_modules/gray-matter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-2.1.1.tgz", + "integrity": "sha512-vbmvP1Fe/fxuT2QuLVcqb2BfK7upGhhbLIt9/owWEvPYrZZEkelLcq2HqzxosV+PQ67dUFLaAeNpH7C4hhICAA==", "dependencies": { - "isobject": "^3.0.1" + "ansi-red": "^0.1.1", + "coffee-script": "^1.12.4", + "extend-shallow": "^2.0.1", + "js-yaml": "^3.8.1", + "toml": "^2.3.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/is-plain-object/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "sprintf-js": "~1.0.2" } }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dependencies": { - "is-unc-path": "^1.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/is-shared-array-buffer": { + "node_modules/gray-matter/node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/gulp-header": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/gulp-header/-/gulp-header-1.8.12.tgz", + "integrity": "sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==", + "deprecated": "Removed event-stream from gulp-header", "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "concat-with-sourcemaps": "*", + "lodash.template": "^4.4.0", + "through2": "^2.0.0" } }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dependencies": { - "has-tostringtag": "^1.0.0" + "ajv": "^6.12.3", + "har-schema": "^2.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "unc-path-regex": "^0.1.2" + "es-define-property": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz", - "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-windows": { + "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dependencies": { - "is-docker": "^2.0.0" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { - "isarray": "1.0.0" + "function-bind": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/isobject/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "peerDependencies": { - "ws": "*" + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + "node_modules/helmet": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.0.0.tgz", + "integrity": "sha512-VyusHLEIIO5mjQPUI1wpOAEu+wl6Q0998jzTxqUYGE45xCIcAxy3MsbEK/yyJUJ3ADeMoB6MornPH6GMWAf+Pw==", + "engines": { + "node": ">=18.0.0" + } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/hexoid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz", + "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=10" + "node": ">= 14" } }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" }, "engines": { - "node": ">=8" + "node": ">=0.8", + "npm": ">=1.3.7" } }, - "node_modules/iterall": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", - "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" - }, - "node_modules/jackspeak": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", - "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", - "dev": true, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "agent-base": "^7.0.2", + "debug": "4" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": ">= 14" } }, - "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, - "bin": { - "jiti": "bin/jiti.js" + "engines": { + "node": ">=16.17.0" } }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", - "dev": true - }, - "node_modules/jose": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.3.tgz", - "integrity": "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA==", + "node_modules/husky": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", + "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/jpeg-js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", - "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" - }, - "node_modules/js-git": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", - "integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==", - "dependencies": { - "bodec": "^0.1.0", - "culvert": "^0.1.2", - "git-sha1": "^0.1.2", - "pako": "^0.2.5" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "bin": { - "jsesc": "bin/jsesc" + "husky": "bin.js" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", - "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", - "dev": true, + "node_modules/i18n": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", + "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", "dependencies": { - "call-bind": "^1.0.5", - "isarray": "^2.0.5", - "jsonify": "^0.0.1", - "object-keys": "^1.1.1" + "@messageformat/core": "^3.0.0", + "debug": "^4.3.3", + "fast-printf": "^1.6.9", + "make-plural": "^7.0.0", + "math-interval-parser": "^2.0.1", + "mustache": "^4.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/mashpie" } }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/json-to-pretty-yaml": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", - "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", - "dev": true, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "remedial": "^1.0.7", - "remove-trailing-spaces": "^1.0.6" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">= 0.2.0" + "node": ">=0.10.0" } }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/image-hash": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/image-hash/-/image-hash-5.3.2.tgz", + "integrity": "sha512-of8SekDXKFoaK4R93dP/Lzw6+NRGag8Jr9YlIIZ9jJVn9KYLfYVo/ARbKtbRn+tdTz/wDzBObx6yflKpLSYbxA==", "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "@cwasm/webp": "^0.1.5", + "file-type": "^16.5.3", + "jpeg-js": "^0.4.0", + "pngjs": "^6.0.0", + "request": "^2.81.0" } }, - "node_modules/jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "node_modules/immutable": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", + "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsonwebtoken/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "node_modules/import-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", + "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", + "dev": true, + "engines": { + "node": ">=12.2" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "engines": { - "node": ">=10" + "node": ">=0.8.19" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "engines": { - "node": ">=0.6.0" + "node": ">=8" } }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" } }, - "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", - "engines": { - "node": ">=12.0.0" + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/ioredis": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", + "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", "dependencies": { - "json-buffer": "3.0.1" + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" } }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "dependencies": { - "is-buffer": "^1.1.5" + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" }, "engines": { - "node": ">=0.10.0" + "node": ">= 12" } }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, - "node_modules/lazy": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", - "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "engines": { - "node": ">=0.2.0" + "node": ">= 0.10" } }, - "node_modules/lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==", + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, "dependencies": { - "set-getter": "^0.1.0" + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, - "engines": { - "node": ">=14" + "dependencies": { + "has-bigints": "^1.0.1" }, "funding": { - "url": "https://github.com/sponsors/antonk52" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "peer": true, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dependencies": { - "uc.micro": "^2.0.0" + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/lint-staged": { - "version": "15.2.10", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", - "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "node_modules/is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha512-PDRu1vVip5dGQg5tfn2qVCCyxbBYu5MhYUJwSfL/RoGBI97n1fxvilVazxzptZW0gcmsMH17H4EVZZI5E/RSeA==", "dev": true, - "dependencies": { - "chalk": "~5.3.0", - "commander": "~12.1.0", - "debug": "~4.3.6", - "execa": "~8.0.1", - "lilconfig": "~3.1.2", - "listr2": "~8.2.4", - "micromatch": "~4.0.8", - "pidtree": "~0.6.0", - "string-argv": "~0.3.2", - "yaml": "~2.5.0" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, "engines": { - "node": ">=18.12.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "dependencies": { - "environment": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, "dependencies": { - "restore-cursor": "^5.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/lint-staged/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/listr2": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", - "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", - "dev": true, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/lint-staged/node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "node_modules/is-lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", + "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==", "dev": true, "dependencies": { - "get-east-asian-width": "^1.0.0" - }, + "tslib": "^2.0.3" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, + "node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" + "kind-of": "^3.0.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { - "mimic-function": "^5.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "node_modules/is-plain-object/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "is-unc-path": "^1.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "call-bind": "^1.0.7" }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lint-staged/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/list-item": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", - "integrity": "sha512-S3D0WZ4J6hyM8o5SNKWaMYB1ALSacPZ2nHGEuCjmHZ+dc03gFeNZoNDcqfcnO4vDhTZmNrqrpYZCdXsRh22bzw==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, "dependencies": { - "expand-range": "^1.8.1", - "extend-shallow": "^2.0.1", - "is-number": "^2.1.0", - "repeat-string": "^1.5.2" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/listr2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", - "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=12" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "which-typed-array": "^1.1.14" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "unc-path-regex": "^0.1.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "engines": { "node": ">=10" }, @@ -12178,277 +13318,350 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + "node_modules/is-upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz", + "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/lodash.lowercase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz", - "integrity": "sha512-UcvP1IZYyDKyEL64mmrwoA1AbFu5ahojhTtkOUr1K9dbuxzS9ev8i4TxMMGCqRC9TE8uDaSoufNAXxRPNTseVA==", + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + "node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + "node_modules/isobject/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "node_modules/lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "peerDependencies": { + "ws": "*" } }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dependencies": { - "lodash._reinterpolate": "^3.0.0" + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/logform": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", - "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "node_modules/iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" + }, + "node_modules/jackspeak": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.1.tgz", + "integrity": "sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==", + "dev": true, "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">= 12.0.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/logform/node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", - "engines": { - "node": ">=0.1.90" + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "devOptional": true, + "bin": { + "jiti": "bin/jiti.js" } }, - "node_modules/loglevel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", - "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", - "engines": { - "node": ">= 0.6.0" - }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", + "dev": true + }, + "node_modules/jose": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.3.tgz", + "integrity": "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA==", + "dev": true, "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" + "url": "https://github.com/sponsors/panva" } }, - "node_modules/long": { + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, + "node_modules/js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==", + "dependencies": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, + "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "argparse": "^2.0.1" }, "bin": { - "loose-envify": "cli.js" + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/loupe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", - "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" } }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", + "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", "dev": true, "dependencies": { - "tslib": "^2.0.3" + "call-bind": "^1.0.5", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lower-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz", - "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json-to-pretty-yaml": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", + "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", "dev": true, "dependencies": { - "tslib": "^2.0.3" + "remedial": "^1.0.7", + "remove-trailing-spaces": "^1.0.6" + }, + "engines": { + "node": ">= 0.2.0" } }, - "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "peer": true - }, - "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", - "dev": true, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/magicast": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", - "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", "dev": true, - "dependencies": { - "@babel/parser": "^7.24.4", - "@babel/types": "^7.24.0", - "source-map-js": "^1.2.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dependencies": { - "semver": "^7.5.3" + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12", + "npm": ">=6" } }, - "node_modules/make-dir/node_modules/lru-cache": { + "node_modules/jsonwebtoken/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -12456,11 +13669,10 @@ "node": ">=10" } }, - "node_modules/make-dir/node_modules/semver": { + "node_modules/jsonwebtoken/node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -12471,221 +13683,355 @@ "node": ">=10" } }, - "node_modules/make-plural": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", - "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "peer": true, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==", "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" + "set-getter": "^0.1.0" }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/markdown-it/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "peer": true, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": ">=0.12" + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/markdown-it/node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "peer": true + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, - "node_modules/markdown-link": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", - "integrity": "sha512-TurLymbyLyo+kAUUAV9ggR9EPcDjP/ctlv9QAFiqUH7c+t6FlsbivPo9OKTU8xdOx9oNd2drW/Fi5RRElQbUqA==", - "engines": { - "node": ">=0.10.0" + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "peer": true, + "dependencies": { + "uc.micro": "^2.0.0" } }, - "node_modules/markdown-toc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.2.0.tgz", - "integrity": "sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==", + "node_modules/lint-staged": { + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", + "dev": true, "dependencies": { - "concat-stream": "^1.5.2", - "diacritics-map": "^0.1.0", - "gray-matter": "^2.1.0", - "lazy-cache": "^2.0.2", - "list-item": "^1.1.1", - "markdown-link": "^0.1.1", - "minimist": "^1.2.0", - "mixin-deep": "^1.1.3", - "object.pick": "^1.2.0", - "remarkable": "^1.7.1", - "repeat-string": "^1.6.1", - "strip-color": "^0.1.0" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" }, "bin": { - "markdown-toc": "cli.js" + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/math-interval-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", - "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==", + "node_modules/lint-staged/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "dependencies": { + "environment": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/lint-staged/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "node_modules/lint-staged/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, "engines": { - "node": ">= 8" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/meros": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", - "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", + "node_modules/lint-staged/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "dependencies": { + "restore-cursor": "^5.0.0" + }, "engines": { - "node": ">=13" + "node": ">=18" }, - "peerDependencies": { - "@types/node": ">=13" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/lint-staged/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/lint-staged/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/lint-staged/node_modules/listr2": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", + "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", + "dev": true, "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=8.6" + "node": ">=18.0.0" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" + "node_modules/lint-staged/node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/lint-staged/node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/lint-staged/node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, "dependencies": { - "mime-db": "1.52.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/lint-staged/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, + "dependencies": { + "mimic-function": "^5.0.0" + }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/lint-staged/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, "engines": { "node": ">=18" }, @@ -12693,2166 +14039,2353 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/lint-staged/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/lint-staged/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/lint-staged/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "node_modules/lint-staged/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "node_modules/list-item": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", + "integrity": "sha512-S3D0WZ4J6hyM8o5SNKWaMYB1ALSacPZ2nHGEuCjmHZ+dc03gFeNZoNDcqfcnO4vDhTZmNrqrpYZCdXsRh22bzw==", "dependencies": { - "is-plain-object": "^2.0.4" + "expand-range": "^1.8.1", + "extend-shallow": "^2.0.1", + "is-number": "^2.1.0", + "repeat-string": "^1.5.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/module-details-from-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" - }, - "node_modules/mongodb": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", - "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", + "node_modules/listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, "dependencies": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.7.0", - "mongodb-connection-string-url": "^3.0.0" + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=16.20.1" + "node": ">=12" }, "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" + "enquirer": ">= 2.3.0 < 3" }, "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { + "enquirer": { "optional": true } } }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", - "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^13.0.0" - } - }, - "node_modules/mongoose": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.3.2.tgz", - "integrity": "sha512-3JcpDjFI25cF/3xpu+4+9nM0lURQTNLcP86X83+LvuICdn453QQLmhSrUr2IPM/ffLiDE9KPl9slNb2s0hZPpg==", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { - "bson": "^6.5.0", - "kareem": "2.6.3", - "mongodb": "6.5.0", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=16.20.1" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, - "node_modules/mongoose-paginate-v2": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/mongoose-paginate-v2/-/mongoose-paginate-v2-1.8.3.tgz", - "integrity": "sha512-Fkg9amsmtRkqUQ19kwOvw6XodkqXoySr82MkV5XPeD+1u/m68tWnDcz3xRwDPzlIsAr1ctx/4Rz/bnfD3PIJqQ==", - "engines": { - "node": ">=4.0.0" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", - "integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dependencies": { - "@mongodb-js/saslprep": "^1.1.5", - "bson": "^6.4.0", - "mongodb-connection-string-url": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=16.20.1" - }, - "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" + "node": ">=10" }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mongoose/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" }, - "node_modules/morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.lowercase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.lowercase/-/lodash.lowercase-4.3.0.tgz", + "integrity": "sha512-UcvP1IZYyDKyEL64mmrwoA1AbFu5ahojhTtkOUr1K9dbuxzS9ev8i4TxMMGCqRC9TE8uDaSoufNAXxRPNTseVA==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", "dependencies": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "engines": { - "node": ">= 0.8.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" } }, - "node_modules/morgan/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dependencies": { - "ms": "2.0.0" + "lodash._reinterpolate": "^3.0.0" } }, - "node_modules/morgan/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dependencies": { - "ee-first": "1.1.1" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mquery": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", - "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { - "debug": "4.x" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": { - "mustache": "bin/mustache" + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" } }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "node_modules/logform/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } }, - "node_modules/nanoid": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", - "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.js" - }, + "node_modules/loglevel": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", + "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", "engines": { - "node": "^18 || >=20" + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, - "node_modules/needle": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", - "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" + "loose-envify": "cli.js" } }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, "dependencies": { - "ms": "^2.1.1" + "tslib": "^2.0.3" } }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" + "node_modules/lower-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz", + "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" } }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "engines": { - "node": ">= 0.4.0" + "node": ">=12" } }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "peer": true + }, + "node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, + "license": "MIT", "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + "node_modules/magicast": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.4.tgz", + "integrity": "sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.4", + "@babel/types": "^7.24.0", + "source-map-js": "^1.2.0" + } }, - "node_modules/node-addon-api": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", - "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, "engines": { - "node": "^16 || ^18 || >= 20" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/make-dir/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { - "whatwg-url": "^5.0.0" + "yallist": "^4.0.0" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=10" } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node_modules/nodemailer": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", - "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", - "license": "MIT-0", + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=6.0.0" + "node": ">=10" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/make-plural": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", + "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "peer": true, "dependencies": { - "path-key": "^4.0.0" + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "peer": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, + "node_modules/markdown-it/node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "peer": true + }, + "node_modules/markdown-link": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", + "integrity": "sha512-TurLymbyLyo+kAUUAV9ggR9EPcDjP/ctlv9QAFiqUH7c+t6FlsbivPo9OKTU8xdOx9oNd2drW/Fi5RRElQbUqA==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/nssocket": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", - "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", + "node_modules/markdown-toc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/markdown-toc/-/markdown-toc-1.2.0.tgz", + "integrity": "sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==", "dependencies": { - "eventemitter2": "~0.4.14", - "lazy": "~1.0.11" + "concat-stream": "^1.5.2", + "diacritics-map": "^0.1.0", + "gray-matter": "^2.1.0", + "lazy-cache": "^2.0.2", + "list-item": "^1.1.1", + "markdown-link": "^0.1.1", + "minimist": "^1.2.0", + "mixin-deep": "^1.1.3", + "object.pick": "^1.2.0", + "remarkable": "^1.7.1", + "repeat-string": "^1.6.1", + "strip-color": "^0.1.0" + }, + "bin": { + "markdown-toc": "cli.js" }, "engines": { - "node": ">= 0.10.x" + "node": ">=0.10.0" } }, - "node_modules/nssocket/node_modules/eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" - }, - "node_modules/nullthrows": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "dev": true - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "node_modules/math-interval-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", + "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==", "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "engines": { - "node": ">= 0.4" + "node": ">= 8" } }, - "node_modules/object-path": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", - "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", + "node_modules/meros": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", + "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", "engines": { - "node": ">= 10.12.0" + "node": ">=13" + }, + "peerDependencies": { + "@types/node": ">=13" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.6" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "isobject": "^3.0.1" + "mime-db": "1.52.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/object.pick/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dependencies": { - "ee-first": "1.1.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" } }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dependencies": { - "fn.name": "1.x.x" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dependencies": { - "mimic-fn": "^4.0.0" + "is-plain-object": "^2.0.4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + }, + "node_modules/mongodb": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", + "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==", "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" + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.3.2.tgz", + "integrity": "sha512-3JcpDjFI25cF/3xpu+4+9nM0lURQTNLcP86X83+LvuICdn453QQLmhSrUr2IPM/ffLiDE9KPl9slNb2s0hZPpg==", + "dependencies": { + "bson": "^6.5.0", + "kareem": "2.6.3", + "mongodb": "6.5.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" }, "engines": { - "node": ">=10" + "node": ">=16.20.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/mongoose" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, + "node_modules/mongoose-paginate-v2": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/mongoose-paginate-v2/-/mongoose-paginate-v2-1.8.3.tgz", + "integrity": "sha512-Fkg9amsmtRkqUQ19kwOvw6XodkqXoySr82MkV5XPeD+1u/m68tWnDcz3xRwDPzlIsAr1ctx/4Rz/bnfD3PIJqQ==", "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/mongoose/node_modules/mongodb": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", + "integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==", "dependencies": { - "yocto-queue": "^0.1.0" + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.4.0", + "mongodb-connection-string-url": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=16.20.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", "dependencies": { - "p-limit": "^3.0.2" + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "aggregate-error": "^3.0.0" + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/pac-proxy-agent": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", - "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "pac-resolver": "^7.0.0", - "socks-proxy-agent": "^8.0.2" + "debug": "4.x" }, "engines": { - "node": ">= 14" + "node": ">=14.0.0" } }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 6.0.0" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" } }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" }, "engines": { - "node": ">=0.8" + "node": "^18 || >=20" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/needle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4.4.x" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/path-case": { + "node_modules/no-case": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dev": true, "dependencies": { - "dot-case": "^3.0.4", + "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/node-addon-api": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", + "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^16 || ^18 || >= 20" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { - "node": ">=8" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "dev": true, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { - "path-root-regex": "^0.1.0" - }, + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/nodemailer": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", + "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", - "dev": true, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "engines": { "node": ">=0.10.0" } }, - "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "path-key": "^4.0.0" }, "engines": { - "node": "20 || >=22" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", - "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "engines": { - "node": "20 || >=22" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/nssocket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", + "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", + "dependencies": { + "eventemitter2": "~0.4.14", + "lazy": "~1.0.11" + }, "engines": { - "node": ">=8" + "node": ">= 0.10.x" } }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "node_modules/nssocket/node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", "dev": true }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "engines": { - "node": ">= 14.16" + "node": "*" } }, - "node_modules/peek-readable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", - "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">=0.10.0" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" } }, - "node_modules/pidusage": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", - "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", - "dependencies": { - "safe-buffer": "^5.2.1" - }, + "node_modules/object-path": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", + "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", "engines": { - "node": ">=10" + "node": ">= 10.12.0" } }, - "node_modules/pm2": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.0.tgz", - "integrity": "sha512-9TrDuckcSEnINoURygr3yfruK20qXuOUPOPQyIh4FIskQduyDNst9ys1XAt9YPY3RyGxVr2+x8Irsdma3klVQw==", + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, "dependencies": { - "@pm2/agent": "~2.0.0", - "@pm2/io": "~6.0.0", - "@pm2/js-api": "~0.8.0", - "@pm2/pm2-version-check": "latest", - "async": "~3.2.0", - "blessed": "0.1.81", - "chalk": "3.0.0", - "chokidar": "^3.5.3", - "cli-tableau": "^2.0.0", - "commander": "2.15.1", - "croner": "~4.1.92", - "dayjs": "~1.11.5", - "debug": "^4.3.1", - "enquirer": "2.3.6", - "eventemitter2": "5.0.1", - "fclone": "1.0.11", - "js-yaml": "~4.1.0", - "mkdirp": "1.0.4", - "needle": "2.4.0", - "pidusage": "~3.0", - "pm2-axon": "~4.0.1", - "pm2-axon-rpc": "~0.7.1", - "pm2-deploy": "~1.0.2", - "pm2-multimeter": "^0.1.2", - "promptly": "^2", - "semver": "^7.2", - "source-map-support": "0.5.21", - "sprintf-js": "1.1.2", - "vizion": "~2.2.1" - }, - "bin": { - "pm2": "bin/pm2", - "pm2-dev": "bin/pm2-dev", - "pm2-docker": "bin/pm2-docker", - "pm2-runtime": "bin/pm2-runtime" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=12.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "pm2-sysmonit": "^1.2.8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pm2-axon": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", - "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, "dependencies": { - "amp": "~0.3.1", - "amp-message": "~0.1.1", - "debug": "^4.3.1", - "escape-string-regexp": "^4.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=5" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pm2-axon-rpc": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", - "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, "dependencies": { - "debug": "^4.3.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": ">=5" + "node": ">= 0.4" } }, - "node_modules/pm2-deploy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", - "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dependencies": { - "run-series": "^1.1.8", - "tv4": "^1.3.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pm2-multimeter": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", - "integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==", - "dependencies": { - "charm": "~0.1.1" - } - }, - "node_modules/pm2-sysmonit": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", - "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", - "optional": true, - "dependencies": { - "async": "^3.2.0", - "debug": "^4.3.1", - "pidusage": "^2.0.21", - "systeminformation": "^5.7", - "tx2": "~1.0.4" + "node": ">=0.10.0" } }, - "node_modules/pm2-sysmonit/node_modules/pidusage": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", - "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", - "optional": true, - "dependencies": { - "safe-buffer": "^5.2.1" - }, + "node_modules/object.pick/node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/pm2/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pm2/node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" - }, - "node_modules/pm2/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { - "yallist": "^4.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8" } }, - "node_modules/pm2/node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "engines": { - "node": ">=10" + "node": ">= 0.8" } }, - "node_modules/pngjs": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", - "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", - "engines": { - "node": ">=12.13.0" + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" } }, - "node_modules/possible-typed-array-names": { + "node_modules/one-time": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "engines": { - "node": ">= 0.4" + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" } }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" + "mimic-fn": "^4.0.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, - "dependencies": { - "asap": "~2.0.3" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/promptly": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", - "integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dependencies": { - "read": "^1.0.4" + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz", + "integrity": "sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==", "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", "debug": "^4.3.4", + "get-uri": "^6.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", + "pac-resolver": "^7.0.0", "socks-proxy-agent": "^8.0.2" }, "engines": { "node": ">= 14" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pvtsutils": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", - "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", - "dev": true, - "dependencies": { - "tslib": "^2.6.1" - } - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dependencies": { - "side-channel": "^1.0.4" + "degenerator": "^5.0.0", + "netmask": "^2.0.2" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 14" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } }, - "node_modules/randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dependencies": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" + "callsites": "^3.0.0" }, "engines": { - "node": ">= 0.10.0" + "node": ">=6" } }, - "node_modules/randomatic/node_modules/is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/randomatic/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/react": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", - "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "peer": true, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/react-dom": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.0" - }, - "peerDependencies": { - "react": "^18.2.0" + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" } }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" } }, - "node_modules/read": { + "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dev": true, "dependencies": { - "mute-stream": "~0.0.4" + "path-root-regex": "^0.1.0" }, "engines": { - "node": ">=0.8" + "node": ">=0.10.0" } }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/readable-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", - "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, "dependencies": { - "readable-stream": "^3.6.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "dev": true, "engines": { - "node": ">= 6" + "node": "20 || >=22" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "engines": { - "node": ">=8.10.0" + "node": ">=8" } }, - "node_modules/redis": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", - "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==", - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.6.0", - "@redis/graph": "1.1.1", - "@redis/json": "1.0.7", - "@redis/search": "1.2.0", - "@redis/time-series": "1.1.0" - } + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 14.16" } }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "dependencies": { - "redis-errors": "^1.0.0" - }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "engines": { - "node": ">= 0.4" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/relay-runtime": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-12.0.0.tgz", - "integrity": "sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==", + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pidusage": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", + "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", "dependencies": { - "@babel/runtime": "^7.0.0", - "fbjs": "^3.0.0", - "invariant": "^2.2.4" + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=10" } }, - "node_modules/remarkable": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", - "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "node_modules/pm2": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.0.tgz", + "integrity": "sha512-9TrDuckcSEnINoURygr3yfruK20qXuOUPOPQyIh4FIskQduyDNst9ys1XAt9YPY3RyGxVr2+x8Irsdma3klVQw==", "dependencies": { - "argparse": "^1.0.10", - "autolinker": "~0.28.0" + "@pm2/agent": "~2.0.0", + "@pm2/io": "~6.0.0", + "@pm2/js-api": "~0.8.0", + "@pm2/pm2-version-check": "latest", + "async": "~3.2.0", + "blessed": "0.1.81", + "chalk": "3.0.0", + "chokidar": "^3.5.3", + "cli-tableau": "^2.0.0", + "commander": "2.15.1", + "croner": "~4.1.92", + "dayjs": "~1.11.5", + "debug": "^4.3.1", + "enquirer": "2.3.6", + "eventemitter2": "5.0.1", + "fclone": "1.0.11", + "js-yaml": "~4.1.0", + "mkdirp": "1.0.4", + "needle": "2.4.0", + "pidusage": "~3.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.1", + "pm2-deploy": "~1.0.2", + "pm2-multimeter": "^0.1.2", + "promptly": "^2", + "semver": "^7.2", + "source-map-support": "0.5.21", + "sprintf-js": "1.1.2", + "vizion": "~2.2.1" }, "bin": { - "remarkable": "bin/remarkable.js" + "pm2": "bin/pm2", + "pm2-dev": "bin/pm2-dev", + "pm2-docker": "bin/pm2-docker", + "pm2-runtime": "bin/pm2-runtime" }, "engines": { - "node": ">= 0.10.0" + "node": ">=12.0.0" + }, + "optionalDependencies": { + "pm2-sysmonit": "^1.2.8" } }, - "node_modules/remarkable/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/pm2-axon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", + "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", "dependencies": { - "sprintf-js": "~1.0.2" + "amp": "~0.3.1", + "amp-message": "~0.1.1", + "debug": "^4.3.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=5" } }, - "node_modules/remarkable/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/remedial": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", - "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", - "dev": true, + "node_modules/pm2-axon-rpc": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", + "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "dependencies": { + "debug": "^4.3.1" + }, "engines": { - "node": "*" + "node": ">=5" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" - }, - "node_modules/remove-trailing-spaces": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", - "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==", - "dev": true - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "node_modules/pm2-deploy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", + "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "dependencies": { + "run-series": "^1.1.8", + "tv4": "^1.3.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "engines": { - "node": ">=0.10" + "node_modules/pm2-multimeter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", + "integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==", + "dependencies": { + "charm": "~0.1.1" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "node_modules/pm2-sysmonit": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", + "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "optional": true, "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "async": "^3.2.0", + "debug": "^4.3.1", + "pidusage": "^2.0.21", + "systeminformation": "^5.7", + "tx2": "~1.0.4" + } + }, + "node_modules/pm2-sysmonit/node_modules/pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "optional": true, + "dependencies": { + "safe-buffer": "^5.2.1" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "node_modules/pm2/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.12" + "node": ">=8" } }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "node_modules/pm2/node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "node_modules/pm2/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=0.6" + "node": ">=10" } }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "node_modules/pm2/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "uuid": "bin/uuid" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", "engines": { - "node": ">=0.10.0" + "node": ">=12.13.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/require-in-the-middle": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", - "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=6" + "node": "^10 || ^12 || >=14" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "bin": { - "resolve": "bin/resolve" + "nanoid": "bin/nanoid.cjs" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "asap": "~2.0.3" + } + }, + "node_modules/promptly": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", + "integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==", + "dependencies": { + "read": "^1.0.4" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", "dev": true, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "mimic-fn": "^2.1.0" + "side-channel": "^1.0.6" }, "engines": { - "node": ">=6" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dependencies": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, "engines": { - "node": ">= 4" + "node": ">= 0.10.0" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/randomatic/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "engines": { - "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true + "node_modules/randomatic/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.6" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", - "dev": true, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 0.8" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "dependencies": { - "brace-expansion": "^2.0.1" + "loose-envify": "^1.1.0" }, "engines": { - "node": "20 || >=22" + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "react": "^18.3.1" } }, - "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", - "dev": true, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { - "@types/estree": "1.0.5" + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" }, - "bin": { - "rollup": "dist/bin/rollup" + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", - "fsevents": "~2.3.2" + "node": ">=0.8" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, - "node_modules/rrule": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", - "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", "dependencies": { - "tslib": "^2.4.0" + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=0.12.0" + "node": ">= 6" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dependencies": { - "queue-microtask": "^1.2.2" + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" } }, - "node_modules/run-series": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", - "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, + "node_modules/redis": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", + "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==", "dependencies": { - "tslib": "^2.1.0" + "@redis/bloom": "1.2.0", + "@redis/client": "1.6.0", + "@redis/graph": "1.1.1", + "@redis/json": "1.0.7", + "@redis/search": "1.2.0", + "@redis/time-series": "1.1.0" } }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" + "redis-errors": "^1.0.0" }, "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-identifier": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", - "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { "call-bind": "^1.0.6", + "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -14861,554 +16394,729 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "node_modules/relay-runtime": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-12.0.0.tgz", + "integrity": "sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.0.0", + "fbjs": "^3.0.0", + "invariant": "^2.2.4" + } + }, + "node_modules/remarkable": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.4.tgz", + "integrity": "sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==", + "dependencies": { + "argparse": "^1.0.10", + "autolinker": "~0.28.0" + }, + "bin": { + "remarkable": "bin/remarkable.js" + }, "engines": { - "node": ">=10" + "node": ">= 0.10.0" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "node_modules/remarkable/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + "node_modules/remarkable/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/scheduler": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", - "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" + "node_modules/remedial": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", + "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", + "dev": true, + "engines": { + "node": "*" } }, - "node_modules/scuid": { + "node_modules/remove-trailing-separator": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz", - "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" + }, + "node_modules/remove-trailing-spaces": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", + "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==", "dev": true }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "node_modules/require-in-the-middle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", + "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/set-blocking": { + "node_modules/require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dependencies": { - "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.2" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/set-getter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", - "integrity": "sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==", + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, "dependencies": { - "to-object-path": "^0.3.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/shiki": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", - "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", - "peer": true, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", + "dev": true, "dependencies": { - "@shikijs/core": "1.10.3", - "@types/hast": "^3.0.4" + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "node_modules/rimraf/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">= 0.4" + "node": "20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sift": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", - "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/rimraf/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/signedsource": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/signedsource/-/signedsource-1.0.0.tgz", - "integrity": "sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==", - "dev": true - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "dev": true, + "license": "MIT", "dependencies": { - "is-arrayish": "^0.3.1" + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" + "node_modules/rrule": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", + "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=0.12.0" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" } }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "tslib": "^2.1.0" } }, - "node_modules/socks": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", - "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" }, "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", - "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "socks": "^2.7.1" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" }, "engines": { - "node": ">= 14" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/scuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz", + "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "ms": "2.0.0" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "dependencies": { - "memory-pager": "^1.0.2" + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" } }, - "node_modules/sponge-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz", - "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==", + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", "dev": true, "dependencies": { - "tslib": "^2.0.3" + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" } }, - "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/stack-chain": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", - "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==" - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "engines": { - "node": "*" + "node": ">= 0.8.0" } }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "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.2" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" } }, - "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.4" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/set-getter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", + "integrity": "sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==", "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true, + "to-object-path": "^0.3.0" + }, "engines": { - "node": ">=0.6.19" + "node": ">=0.10.0" } }, - "node_modules/string-env-interpolation": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", - "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "dev": true }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" }, - "engines": { - "node": ">=8" + "bin": { + "sha.js": "bin.js" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/string.prototype.repeat": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", - "integrity": "sha512-1BH+X+1hSthZFW+X+JaUkjkkUPwIlLEMJBLANN3hOob3RhEk5snLWNECDnYbgn/m5c5JV7Ersu1Yubaf+05cIA==" + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shiki": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", + "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", + "peer": true, + "dependencies": { + "@shikijs/core": "1.10.3", + "@types/hast": "^3.0.4" + } }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" }, "engines": { "node": ">= 0.4" @@ -15417,1381 +17125,1406 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "ISC" }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/signedsource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signedsource/-/signedsource-1.0.0.tgz", + "integrity": "sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==", + "dev": true + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "is-arrayish": "^0.3.1" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "engines": { "node": ">=8" } }, - "node_modules/strip-bom": { + "node_modules/slice-ansi": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/strip-color": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", - "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==", + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "engines": { - "node": ">=0.10.0" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/strtok3": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", - "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "node_modules/socks": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", + "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^4.1.0" + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">= 10.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", "dependencies": { - "has-flag": "^4.0.0" + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/svg-pan-zoom": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/svg-pan-zoom/-/svg-pan-zoom-3.6.1.tgz", - "integrity": "sha512-JaKkGHHfGvRrcMPdJWkssLBeWqM+Isg/a09H7kgNNajT1cX5AztDTNs+C8UzpCxjCTRrG34WbquwaovZbmSk9g==" - }, - "node_modules/swap-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz", - "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/systeminformation": { - "version": "5.22.6", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.6.tgz", - "integrity": "sha512-hUTQX+bRgIFbv1T/z251NtwGwNIeSyWURnT2BGnsYu6dQNbkiBl4oAwk50acVfITFq1Zvb8KDNgibQK9uGlUGg==", - "optional": true, - "os": [ - "darwin", - "linux", - "win32", - "freebsd", - "openbsd", - "netbsd", - "sunos", - "android" - ], - "bin": { - "systeminformation": "lib/cli.js" - }, "engines": { - "node": ">=8.0.0" - }, - "funding": { - "type": "Buy me a coffee", - "url": "https://www.buymeacoffee.com/systeminfo" + "node": ">=0.10.0" } }, - "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "memory-pager": "^1.0.2" } }, - "node_modules/test-exclude/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/sponge-case": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz", + "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==", "dev": true, "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "tslib": "^2.0.3" } }, - "node_modules/test-exclude/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" }, - "node_modules/test-exclude/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" }, - "engines": { - "node": ">=16 || 14 >=14.18" + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "node_modules/stack-chain": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", + "integrity": "sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug==" }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" } }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" }, - "node_modules/tinyexec": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", - "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", - "dev": true + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" }, - "node_modules/tinypool": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", - "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", - "dev": true, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">= 0.8" } }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "engines": { - "node": ">=14.0.0" + "node": ">=10.0.0" } }, - "node_modules/title-case": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", - "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", - "dev": true, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "tslib": "^2.0.3" + "safe-buffer": "~5.1.0" } }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, "engines": { - "node": ">=0.6.0" + "node": ">=0.6.19" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } + "node_modules/string-env-interpolation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", + "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", + "dev": true }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "kind-of": "^3.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { - "is-number": "^7.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=8.0" - } - }, - "node_modules/to-regex-range/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" + "node": ">=8" } }, - "node_modules/token-types": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", - "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "node_modules/string.prototype.repeat": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", + "integrity": "sha512-1BH+X+1hSthZFW+X+JaUkjkkUPwIlLEMJBLANN3hOob3RhEk5snLWNECDnYbgn/m5c5JV7Ersu1Yubaf+05cIA==" + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, "dependencies": { - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/toml": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", - "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, - "engines": { - "node": ">=0.8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "punycode": "^2.3.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=14" + "node": ">=8" } }, - "node_modules/tr46/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "engines": { - "node": ">= 14.0.0" + "node": ">=4" } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "node_modules/strip-color": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", + "integrity": "sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==", "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" + "node": ">=0.10.0" } }, - "node_modules/ts-log": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.5.tgz", - "integrity": "sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==", - "dev": true - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" }, - "bin": { - "json5": "lib/cli.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, - "node_modules/tsx": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", - "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", - "dev": true, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", "dependencies": { - "esbuild": "~0.23.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/superagent": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz", + "integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==", + "dev": true, "dependencies": { - "safe-buffer": "^5.0.1" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.1", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" }, "engines": { - "node": "*" + "node": ">=14.18.0" } }, - "node_modules/tv4": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", - "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=4.0.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/tx2": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", - "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", - "optional": true, + "node_modules/supertest": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz", + "integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==", + "dev": true, "dependencies": { - "json-stringify-safe": "^5.0.1" + "methods": "^1.1.2", + "superagent": "^9.0.1" + }, + "engines": { + "node": ">=14.18.0" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "prelude-ls": "^1.2.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/svg-pan-zoom": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/svg-pan-zoom/-/svg-pan-zoom-3.6.1.tgz", + "integrity": "sha512-JaKkGHHfGvRrcMPdJWkssLBeWqM+Isg/a09H7kgNNajT1cX5AztDTNs+C8UzpCxjCTRrG34WbquwaovZbmSk9g==" + }, + "node_modules/swap-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz", + "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==", + "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "tslib": "^2.0.3" + } + }, + "node_modules/systeminformation": { + "version": "5.22.6", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.6.tgz", + "integrity": "sha512-hUTQX+bRgIFbv1T/z251NtwGwNIeSyWURnT2BGnsYu6dQNbkiBl4oAwk50acVfITFq1Zvb8KDNgibQK9uGlUGg==", + "optional": true, + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" }, "engines": { - "node": ">= 0.6" + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "node_modules/test-exclude/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { - "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" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">= 0.4" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "node_modules/test-exclude/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.7", - "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" - }, - "engines": { - "node": ">= 0.4" + "@isaacs/cliui": "^8.0.2" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "node_modules/test-exclude/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/test-exclude/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "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", - "possible-typed-array-names": "^1.0.0" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, - "node_modules/typedoc": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", - "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", - "peer": true, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dependencies": { - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "shiki": "^1.9.1", - "yaml": "^2.4.5" - }, - "bin": { - "typedoc": "bin/typedoc" - }, + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.0.tgz", + "integrity": "sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.1.tgz", + "integrity": "sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x" + "node": "^18.0.0 || >=20.0.0" } }, - "node_modules/typedoc-plugin-markdown": { - "version": "4.2.7", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.7.tgz", - "integrity": "sha512-bLsQdweSm48P9j6kGqQ3/4GCH5zu2EnURSkkxqirNc+uVFE9YK825ogDw+WbNkRHIV6eZK/1U43gT7YfglyYOg==", + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typedoc": "0.26.x" + "node": ">=14.0.0" } }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/title-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", + "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" }, "engines": { - "node": ">=14.17" + "node": ">=0.6.0" } }, - "node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "peer": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "kind-of": "^3.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0" } }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "node_modules/to-regex-range/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { - "node": ">= 10.0.0" + "node": ">=0.6" } }, - "node_modules/unixify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", - "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", "dependencies": { - "normalize-path": "^2.1.1" + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/unixify/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "node_modules/toml": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", + "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==" + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "psl": "^1.1.28", + "punycode": "^2.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "punycode": "^2.3.0" }, + "engines": { + "node": ">=14" + } + }, + "node_modules/tr46/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, "bin": { - "update-browserslist-db": "cli.js" + "tree-kill": "cli.js" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "engines": { + "node": ">=16" }, "peerDependencies": { - "browserslist": ">= 4.21.0" + "typescript": ">=4.2.0" } }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "node_modules/ts-log": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.5.tgz", + "integrity": "sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==", + "dev": true + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { - "tslib": "^2.0.3" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "dependencies": { - "tslib": "^2.0.3" + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/tsx": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", + "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", + "dev": true, + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, "engines": { - "node": ">=6" + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" } }, - "node_modules/urlpattern-polyfill": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", - "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, "engines": { - "node": ">= 0.4.0" + "node": "*" } }, - "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/validator": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", - "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", - "engines": { - "node": ">= 0.10" + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/tx2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", + "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "optional": true, + "dependencies": { + "json-stringify-safe": "^5.0.1" } }, - "node_modules/value-or-promise": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", - "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">=12" + "node": ">= 0.8.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/verror/node_modules/core-util-is": { + "node_modules/typed-array-buffer": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "node_modules/vite": { - "version": "5.4.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", - "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, - "bin": { - "vite": "bin/vite.js" + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "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" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.1.tgz", - "integrity": "sha512-N/mGckI1suG/5wQI35XeR9rsMsPqKXzq1CdUndzVstBj/HvyxxGctwnK6WX43NGt5L3Z5tcRf83g4TITKJhPrA==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.6", - "pathe": "^1.1.2", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" + "available-typed-arrays": "^1.0.7", + "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" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "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", + "possible-typed-array-names": "^1.0.0" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typedoc": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", + "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", + "peer": true, + "dependencies": { + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.9.1", + "yaml": "^2.4.5" + }, + "bin": { + "typedoc": "bin/typedoc" + }, "engines": { - "node": ">=12" + "node": ">= 18" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x" } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], + "node_modules/typedoc-plugin-markdown": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.2.7.tgz", + "integrity": "sha512-bLsQdweSm48P9j6kGqQ3/4GCH5zu2EnURSkkxqirNc+uVFE9YK825ogDw+WbNkRHIV6eZK/1U43gT7YfglyYOg==", "engines": { - "node": ">=12" + "node": ">= 18" + }, + "peerDependencies": { + "typedoc": "0.26.x" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=12" + "node": ">=14.17" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], + "node_modules/ua-parser-js": { + "version": "1.0.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", + "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", "dev": true, - "optional": true, - "os": [ - "darwin" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } ], "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "peer": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "engines": { - "node": ">=12" + "node": ">= 10.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/unixify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", + "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", + "dependencies": { + "normalize-path": "^2.1.1" + }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/unixify/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], - "engines": { - "node": ">=12" + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "tslib": "^2.0.3" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], + "node_modules/urlpattern-polyfill": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", + "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { - "node": ">=12" + "node": ">= 0.4.0" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" + "node_modules/uuid": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.1.tgz", + "integrity": "sha512-wt9UB5EcLhnboy1UvA1mvGPXkIIrHSu+3FmUksARfdVw9tuPf3CH/CohxO0Su1ApoKAeT6BVzAJIvjTuQVSmuQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", "engines": { - "node": ">=12" + "node": ">= 0.10" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/value-or-promise": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", + "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", "engines": { "node": ">=12" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/vite": { + "version": "5.4.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", + "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=12" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], + "node_modules/vite-node": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.3.tgz", + "integrity": "sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.6", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, "engines": { - "node": ">=12" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { @@ -16802,6 +18535,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -16816,6 +18550,7 @@ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -16849,18 +18584,19 @@ } }, "node_modules/vitest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.1.tgz", - "integrity": "sha512-97We7/VC0e9X5zBVkvt7SGQMGrRtn3KtySFQG5fpaMlS+l62eeXRQO633AYhSTC3z7IMebnPPNjGXVGNRFlxBA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.3.tgz", + "integrity": "sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==", "dev": true, + "license": "MIT", "dependencies": { - "@vitest/expect": "2.1.1", - "@vitest/mocker": "2.1.1", - "@vitest/pretty-format": "^2.1.1", - "@vitest/runner": "2.1.1", - "@vitest/snapshot": "2.1.1", - "@vitest/spy": "2.1.1", - "@vitest/utils": "2.1.1", + "@vitest/expect": "2.1.3", + "@vitest/mocker": "2.1.3", + "@vitest/pretty-format": "^2.1.3", + "@vitest/runner": "2.1.3", + "@vitest/snapshot": "2.1.3", + "@vitest/spy": "2.1.3", + "@vitest/utils": "2.1.3", "chai": "^5.1.1", "debug": "^4.3.6", "magic-string": "^0.30.11", @@ -16871,7 +18607,7 @@ "tinypool": "^1.0.0", "tinyrainbow": "^1.2.0", "vite": "^5.0.0", - "vite-node": "2.1.1", + "vite-node": "2.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -16886,8 +18622,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.1", - "@vitest/ui": "2.1.1", + "@vitest/browser": "2.1.3", + "@vitest/ui": "2.1.3", "happy-dom": "*", "jsdom": "*" }, @@ -17053,6 +18789,7 @@ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, + "license": "MIT", "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" @@ -17065,9 +18802,10 @@ } }, "node_modules/winston": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.14.2.tgz", - "integrity": "sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.15.0.tgz", + "integrity": "sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==", + "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", @@ -17178,7 +18916,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { "version": "8.18.0", diff --git a/package.json b/package.json index cd9c53ef9c..4da0195320 100644 --- a/package.json +++ b/package.json @@ -47,38 +47,39 @@ }, "homepage": "https://github.com/PalisadoesFoundation/talawa-api#readme", "dependencies": { - "@apollo/server": "^4.11.0", + "@apollo/server": "^4.11.2", + "@aws-sdk/client-s3": "^3.675.0", "@faker-js/faker": "^9.0.1", "@graphql-inspector/cli": "^5.0.6", - "@graphql-tools/resolvers-composition": "^7.0.1", + "@graphql-tools/resolvers-composition": "^7.0.2", "@graphql-tools/schema": "^10.0.6", "@graphql-tools/utils": "^10.3.2", "@parcel/watcher": "^2.4.1", "@types/graphql-upload": "^16.0.5", "@types/yargs": "^17.0.33", "@typescript-eslint/eslint-plugin": "^8.2.0", - "@typescript-eslint/parser": "^8.0.1", - "axios": "^1.7.4", + "@typescript-eslint/parser": "^8.11.0", + "axios": "^1.7.7", "bcryptjs": "^2.4.3", "bluebird": "3.7.2", "cls-hooked": "^4.2.2", "copy-paste": "^1.5.3", "cors": "^2.8.5", "cross-env": "^7.0.3", - "date-fns": "^3.3.1", + "date-fns": "^4.1.0", "dotenv": "^16.4.1", "express": "^4.19.2", "express-mongo-sanitize": "^2.2.0", - "express-rate-limit": "^7.4.0", + "express-rate-limit": "^7.4.1", "graphql": "^16.9.0", "graphql-depth-limit": "^1.1.0", "graphql-scalars": "^1.20.1", "graphql-subscriptions": "^2.0.0", "graphql-tag": "^2.12.6", - "graphql-upload": "^16.0.2", - "graphql-voyager": "^2.0.0", + "graphql-upload": "^17.0.0", + "graphql-voyager": "^2.1.0", "graphql-ws": "^5.16.0", - "helmet": "^7.1.0", + "helmet": "^8.0.0", "i18n": "^0.15.1", "image-hash": "^5.3.1", "ioredis": "^5.4.1", @@ -90,59 +91,67 @@ "mongoose": "^8.3.2", "mongoose-paginate-v2": "^1.8.3", "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", "nanoid": "^5.0.7", - "nodemailer": "^6.9.15", + "nodemailer": "^6.9.16", "pm2": "^5.4.0", "redis": "^4.7.0", "rrule": "^2.8.1", "typedoc-plugin-markdown": "^4.2.7", - "uuid": "^10.0.0", + "uuid": "^11.0.1", "validator": "^13.12.0", - "winston": "^3.14.2", + "winston": "^3.15.0", "ws": "^8.18.0", "yargs": "^17.7.2", "zod": "^3.23.8", "zod-error": "^1.5.0" }, "devDependencies": { - "@graphql-codegen/cli": "^5.0.2", - "@graphql-codegen/typescript": "^4.0.9", + "@eslint/compat": "^1.1.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "^8.57.0", + "@graphql-codegen/cli": "^5.0.3", + "@graphql-codegen/typescript": "^4.1.0", "@graphql-codegen/typescript-resolvers": "^4.2.1", "@graphql-eslint/eslint-plugin": "^3.20.1", "@parcel/watcher": "^2.4.1", "@types/bcryptjs": "^2.4.6", - "@types/cls-hooked": "^4.3.8", + "@types/cls-hooked": "^4.3.9", "@types/copy-paste": "^1.1.30", "@types/cors": "^2.8.17", "@types/express": "^4.17.17", - "@types/express-rate-limit": "^6.0.0", + "@types/express-rate-limit": "^6.0.2", "@types/graphql-depth-limit": "^1.1.6", "@types/i18n": "^0.13.12", "@types/inquirer": "^9.0.7", "@types/jsonwebtoken": "^9.0.7", - "@types/lodash": "^4.17.7", + "@types/lodash": "^4.17.13", "@types/mongoose-paginate-v2": "^1.6.5", "@types/morgan": "^1.9.9", - "@types/node": "^22.5.4", - "@types/nodemailer": "^6.4.15", + "@types/multer": "^1.4.12", + "@types/node": "^22.9.0", + "@types/nodemailer": "^6.4.16", + "@types/supertest": "^6.0.2", "@types/uuid": "^10.0.0", - "@types/validator": "^13.12.0", - "@vitest/coverage-v8": "^2.1.1", + "@types/validator": "^13.12.2", + "@vitest/coverage-v8": "^2.1.3", "cls-bluebird": "^2.1.0", - "concurrently": "^9.0.0", - "eslint": "^8.56.0", + "concurrently": "^9.0.1", + "eslint": "^9.10.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-tsdoc": "^0.3.0", "get-graphql-schema": "^2.1.2", - "graphql-markdown": "^7.1.0", - "husky": "^9.1.5", + "globals": "^15.12.0", + "graphql-markdown": "^7.3.0", + "husky": "^9.1.6", "lint-staged": "^15.2.10", "prettier": "^3.3.3", "rimraf": "^6.0.1", + "supertest": "^7.0.0", "tsx": "^4.19.1", "typescript": "^5.5.4", - "vitest": "^2.0.5" + "vitest": "^2.1.3" }, "overrides": { "graphql-voyager": { diff --git a/public/markdown/images/recaptcha_set_up.png b/public/markdown/images/recaptcha_set_up.png new file mode 100644 index 0000000000000000000000000000000000000000..5e9d6a0edaf6dee0a0a2b0eb6bae97adb5619fe7 GIT binary patch literal 165262 zcmeFZXH-*L^9M{35ClO%iU>gwk=~>T(nLk+(vc1lI-&PaM8HC^(VIw9dXZj2@4fdb z9YPI(1d{jQz0Y&+QhC<<;r;Ti^=GY+lasw?&z_k*`!}=a
DEE&mF5*!>HvL}xp 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 A0{{R3 literal 0 HcmV?d00001 diff --git a/public/markdown/images/recaptcha_set_up.webp b/public/markdown/images/recaptcha_set_up.webp deleted file mode 100644 index 1a59f301b1e47490f1315e5234eb249d417d4d11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34838 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 Q2D&mpl%-cX|H2pm01$Pyi~s-t diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000000..ccbd3b8344 --- /dev/null +++ b/renovate.json @@ -0,0 +1,17 @@ +{ + "extends": ["config:base"], + "baseBranches": ["develop"], + "schedule": ["every weekend"], + "packageRules": [ + { + "packagePatterns": ["*"], + "groupName": "All Minor Updates", + "group": true, + "commitMessageAction": "Update dependencies (renov): " + } + ], + "labels": ["dependencies"], + "branchPrefix": "renovate/", + "automergeType": "pr", + "automerge": true +} diff --git a/schema.graphql b/schema.graphql index c5fb18a0dd..a28cc18bf9 100644 --- a/schema.graphql +++ b/schema.graphql @@ -5,8 +5,11 @@ directive @role(requires: UserType) on FIELD_DEFINITION type ActionItem { _id: ID! actionItemCategory: ActionItemCategory - allotedHours: Float - assignee: User + allottedHours: Float + assignee: EventVolunteer + assigneeGroup: EventVolunteerGroup + assigneeType: String! + assigneeUser: User assigner: User assignmentDate: Date! completionDate: Date! @@ -41,6 +44,7 @@ input ActionItemWhereInput { categoryName: String event_id: ID is_completed: Boolean + orgId: ID } enum ActionItemsOrderByInput { @@ -50,6 +54,11 @@ enum ActionItemsOrderByInput { dueDate_DESC } +input AddPeopleToUserTagInput { + tagId: ID! + userIds: [ID!]! +} + type Address { city: String countryCode: String @@ -190,6 +199,32 @@ input CampaignWhereInput { organizationId: ID } +type Chat { + _id: ID! + admins: [User] + createdAt: DateTime! + creator: User + image: String + isGroup: Boolean! + lastMessageId: String + messages: [ChatMessage] + name: String + organization: Organization + updatedAt: DateTime! + users: [User!]! +} + +type ChatMessage { + _id: ID! + chatMessageBelongsTo: Chat! + createdAt: DateTime! + deletedBy: [User] + messageContent: String! + replyTo: ChatMessage + sender: User! + updatedAt: DateTime! +} + type CheckIn { _id: ID! createdAt: DateTime! @@ -239,6 +274,7 @@ type Community { logoUrl: String name: String! socialMediaUrls: SocialMediaUrls + timeout: Int websiteLink: String } @@ -278,8 +314,9 @@ interface ConnectionPageInfo { scalar CountryCode input CreateActionItemInput { - allotedHours: Float + allottedHours: Float assigneeId: ID! + assigneeType: String! dueDate: Date eventId: ID preCompletionNotes: String @@ -338,8 +375,6 @@ type CreateCommentPayload { userErrors: [CreateCommentError!]! } -union CreateDirectChatError = OrganizationNotFoundError | UserNotFoundError - union CreateMemberError = MemberNotFoundError | OrganizationNotFoundError | UserNotAuthorizedAdminError | UserNotAuthorizedError | UserNotFoundError type CreateMemberPayload { @@ -549,26 +584,6 @@ type DeletePayload { success: Boolean! } -type DirectChat { - _id: ID! - createdAt: DateTime! - creator: User - messages: [DirectChatMessage] - organization: Organization - updatedAt: DateTime! - users: [User!]! -} - -type DirectChatMessage { - _id: ID! - createdAt: DateTime! - directChatMessageBelongsTo: DirectChat! - messageContent: String! - receiver: User! - sender: User! - updatedAt: DateTime! -} - type Donation { _id: ID! amount: Float! @@ -665,6 +680,8 @@ type Event { startTime: Time title: String! updatedAt: DateTime! + volunteerGroups: [EventVolunteerGroup] + volunteers: [EventVolunteer] } type EventAttendee { @@ -729,21 +746,25 @@ enum EventOrderByInput { type EventVolunteer { _id: ID! + assignments: [ActionItem] createdAt: DateTime! creator: User event: Event - group: EventVolunteerGroup - isAssigned: Boolean - isInvited: Boolean - response: String + groups: [EventVolunteerGroup] + hasAccepted: Boolean! + hoursHistory: [HoursHistory] + hoursVolunteered: Float! + isPublic: Boolean! updatedAt: DateTime! user: User! } type EventVolunteerGroup { _id: ID! + assignments: [ActionItem] createdAt: DateTime! creator: User + description: String event: Event leader: User! name: String @@ -753,20 +774,32 @@ type EventVolunteerGroup { } input EventVolunteerGroupInput { + description: String eventId: ID! - name: String + leaderId: ID! + name: String! + volunteerUserIds: [ID!]! volunteersRequired: Int } +enum EventVolunteerGroupOrderByInput { + assignments_ASC + assignments_DESC + volunteers_ASC + volunteers_DESC +} + input EventVolunteerGroupWhereInput { eventId: ID + leaderName: String name_contains: String - volunteerId: ID + orgId: ID + userId: ID } input EventVolunteerInput { eventId: ID! - groupId: ID! + groupId: ID userId: ID! } @@ -775,6 +808,19 @@ enum EventVolunteerResponse { YES } +input EventVolunteerWhereInput { + eventId: ID + groupId: ID + hasAccepted: Boolean + id: ID + name_contains: String +} + +enum EventVolunteersOrderByInput { + hoursVolunteered_ASC + hoursVolunteered_DESC +} + input EventWhereInput { description: String description_contains: String @@ -828,6 +874,35 @@ interface FieldError { path: [String!]! } +type File { + _id: ID! + archived: Boolean! + archivedAt: DateTime + backupStatus: String! + createdAt: DateTime! + encryption: Boolean! + fileName: String! + hash: Hash! + metadata: FileMetadata! + mimeType: String! + referenceCount: Int! + size: Int! + status: Status! + updatedAt: DateTime! + uri: String! + visibility: FileVisibility! +} + +type FileMetadata { + bucketName: String! + objectKey: String! +} + +enum FileVisibility { + PRIVATE + PUBLIC +} + input ForgotPasswordData { newPassword: String! otpToken: String! @@ -932,24 +1007,14 @@ type Group { updatedAt: DateTime! } -type GroupChat { - _id: ID! - createdAt: DateTime! - creator: User - messages: [GroupChatMessage] - organization: Organization! - title: String! - updatedAt: DateTime! - users: [User!]! +type Hash { + algorithm: String! + value: String! } -type GroupChatMessage { - _id: ID! - createdAt: DateTime! - groupChatMessageBelongsTo: GroupChat! - messageContent: String! - sender: User! - updatedAt: DateTime! +type HoursHistory { + date: Date! + hours: Float! } type InvalidCursor implements FieldError { @@ -1025,6 +1090,10 @@ type MembershipRequest { } input MembershipRequestsWhereInput { + creatorId: ID + creatorId_in: [ID!] + creatorId_not: ID + creatorId_not_in: [ID!] id: ID id_contains: ID id_in: [ID!] @@ -1044,21 +1113,6 @@ type Message { videoUrl: URL } -type MessageChat { - _id: ID! - createdAt: DateTime! - languageBarrier: Boolean - message: String! - receiver: User! - sender: User! - updatedAt: DateTime! -} - -input MessageChatInput { - message: String! - receiver: ID! -} - type MinimumLengthError implements FieldError { limit: Int! message: String! @@ -1077,12 +1131,12 @@ type Mutation { addLanguageTranslation(data: LanguageInput!): Language! addOrganizationCustomField(name: String!, organizationId: ID!, type: String!): OrganizationCustomField! addOrganizationImage(file: String!, organizationId: String!): Organization! + addPeopleToUserTag(input: AddPeopleToUserTagInput!): UserTag addPledgeToFundraisingCampaign(campaignId: ID!, pledgeId: ID!): FundraisingCampaignPledge! addUserCustomData(dataName: String!, dataValue: Any!, organizationId: ID!): UserCustomData! addUserImage(file: String!): User! - addUserToGroupChat(chatId: ID!, userId: ID!): GroupChat! addUserToUserFamily(familyId: ID!, userId: ID!): UserFamily! - adminRemoveGroup(groupId: ID!): GroupChat! + assignToUserTags(input: TagActionsInput!): UserTag assignUserTag(input: ToggleUserTagAssignInput!): User blockPluginCreationBySuperadmin(blockUser: Boolean!, userId: ID!): AppUserProfile! blockUser(organizationId: ID!, userId: ID!): User! @@ -1096,8 +1150,8 @@ type Mutation { createAgendaCategory(input: CreateAgendaCategoryInput!): AgendaCategory! createAgendaItem(input: CreateAgendaItemInput!): AgendaItem! createAgendaSection(input: CreateAgendaSectionInput!): AgendaSection! + createChat(data: chatInput!): Chat createComment(data: CommentInput!, postId: ID!): Comment - createDirectChat(data: createChatInput!): DirectChat! createDonation(amount: Float!, nameOfOrg: String!, nameOfUser: String!, orgId: ID!, payPalId: ID!, userId: ID!): Donation! createEvent(data: EventInput!, recurrenceRuleData: RecurrenceRuleInput): Event! createEventVolunteer(data: EventVolunteerInput!): EventVolunteer! @@ -1105,9 +1159,7 @@ type Mutation { createFund(data: FundInput!): Fund! createFundraisingCampaign(data: FundCampaignInput!): FundraisingCampaign! createFundraisingCampaignPledge(data: FundCampaignPledgeInput!): FundraisingCampaignPledge! - createGroupChat(data: createGroupChatInput!): GroupChat! createMember(input: UserAndOrganizationInput!): CreateMemberPayload! - createMessageChat(data: MessageChatInput!): MessageChat! createNote(data: NoteInput!): Note! createOrganization(data: OrganizationInput, file: String): Organization! createPlugin(pluginCreatedBy: String!, pluginDesc: String!, pluginName: String!, uninstalledOrgs: [ID!]): Plugin! @@ -1116,6 +1168,7 @@ type Mutation { createUserFamily(data: createUserFamilyInput!): UserFamily! createUserTag(input: CreateUserTagInput!): UserTag createVenue(data: VenueInput!): Venue + createVolunteerMembership(data: VolunteerMembershipInput!): VolunteerMembership! deleteAdvertisement(id: ID!): DeleteAdvertisementPayload deleteAgendaCategory(id: ID!): ID! deleteDonationById(id: ID!): DeletePayload! @@ -1142,13 +1195,12 @@ type Mutation { removeAgendaItem(id: ID!): AgendaItem! removeAgendaSection(id: ID!): ID! removeComment(id: ID!): Comment - removeDirectChat(chatId: ID!, organizationId: ID!): DirectChat! removeEvent(id: ID!, recurringEventDeleteType: RecurringEventMutationType): Event! removeEventAttendee(data: EventAttendeeInput!): User! removeEventVolunteer(id: ID!): EventVolunteer! removeEventVolunteerGroup(id: ID!): EventVolunteerGroup! + removeFromUserTags(input: TagActionsInput!): UserTag removeFundraisingCampaignPledge(id: ID!): FundraisingCampaignPledge! - removeGroupChat(chatId: ID!): GroupChat! removeMember(data: UserAndOrganizationInput!): Organization! removeOrganization(id: ID!): UserData! removeOrganizationCustomField(customFieldId: ID!, organizationId: ID!): OrganizationCustomField! @@ -1157,7 +1209,6 @@ type Mutation { removeSampleOrganization: Boolean! removeUserCustomData(organizationId: ID!): UserCustomData! removeUserFamily(familyId: ID!): UserFamily! - removeUserFromGroupChat(chatId: ID!, userId: ID!): GroupChat! removeUserFromUserFamily(familyId: ID!, userId: ID!): UserFamily! removeUserImage: User! removeUserTag(id: ID!): UserTag @@ -1165,8 +1216,7 @@ type Mutation { revokeRefreshTokenForUser: Boolean! saveFcmToken(token: String): Boolean! sendMembershipRequest(organizationId: ID!): MembershipRequest! - sendMessageToDirectChat(chatId: ID!, messageContent: String!): DirectChatMessage! - sendMessageToGroupChat(chatId: ID!, messageContent: String!): GroupChatMessage! + sendMessageToChat(chatId: ID!, messageContent: String!, replyTo: ID): ChatMessage! signUp(data: UserInput!, file: String): AuthData! togglePostPin(id: ID!, title: String): Post! unassignUserTag(input: ToggleUserTagAssignInput!): User @@ -1183,7 +1233,7 @@ type Mutation { updateCommunity(data: UpdateCommunityInput!): Boolean! updateEvent(data: UpdateEventInput!, id: ID!, recurrenceRuleData: RecurrenceRuleInput, recurringEventUpdateType: RecurringEventMutationType): Event! updateEventVolunteer(data: UpdateEventVolunteerInput, id: ID!): EventVolunteer! - updateEventVolunteerGroup(data: UpdateEventVolunteerGroupInput, id: ID!): EventVolunteerGroup! + updateEventVolunteerGroup(data: UpdateEventVolunteerGroupInput!, id: ID!): EventVolunteerGroup! updateFund(data: UpdateFundInput!, id: ID!): Fund! updateFundraisingCampaign(data: UpdateFundCampaignInput!, id: ID!): FundraisingCampaign! updateFundraisingCampaignPledge(data: UpdateFundCampaignPledgeInput!, id: ID!): FundraisingCampaignPledge! @@ -1192,10 +1242,12 @@ type Mutation { updateOrganization(data: UpdateOrganizationInput, file: String, id: ID!): Organization! updatePluginStatus(id: ID!, orgId: ID!): Plugin! updatePost(data: PostUpdateInput, id: ID!): Post! + updateSessionTimeout(timeout: Int!): Boolean! updateUserPassword(data: UpdateUserPasswordInput!): UserData! updateUserProfile(data: UpdateUserInput, file: String): User! updateUserRoleInOrganization(organizationId: ID!, role: String!, userId: ID!): Organization! updateUserTag(input: UpdateUserTagInput!): UserTag + updateVolunteerMembership(id: ID!, status: String!): VolunteerMembership! } type Note { @@ -1239,7 +1291,7 @@ type Organization { posts(after: String, before: String, first: PositiveInt, last: PositiveInt): PostsConnection updatedAt: DateTime! userRegistrationRequired: Boolean! - userTags(after: String, before: String, first: PositiveInt, last: PositiveInt): UserTagsConnection + userTags(after: String, before: String, first: PositiveInt, last: PositiveInt, sortedBy: UserTagSortedByInput, where: UserTagWhereInput): UserTagsConnection venues: [Venue] visibleInSearch: Boolean! } @@ -1400,7 +1452,7 @@ type Post { comments: [Comment] createdAt: DateTime! creator: User - imageUrl: URL + file: File likeCount: Int likedBy: [User] organization: Organization! @@ -1408,7 +1460,6 @@ type Post { text: String! title: String updatedAt: DateTime! - videoUrl: URL } type PostEdge { @@ -1487,22 +1538,22 @@ type Query { actionItemCategoriesByOrganization(orderBy: ActionItemsOrderByInput, organizationId: ID!, where: ActionItemCategoryWhereInput): [ActionItemCategory] actionItemsByEvent(eventId: ID!): [ActionItem] actionItemsByOrganization(eventId: ID, orderBy: ActionItemsOrderByInput, organizationId: ID!, where: ActionItemWhereInput): [ActionItem] + actionItemsByUser(orderBy: ActionItemsOrderByInput, userId: ID!, where: ActionItemWhereInput): [ActionItem] adminPlugin(orgId: ID!): [Plugin] advertisementsConnection(after: String, before: String, first: PositiveInt, last: PositiveInt): AdvertisementsConnection agendaCategory(id: ID!): AgendaCategory! agendaItemByEvent(relatedEventId: ID!): [AgendaItem] agendaItemByOrganization(organizationId: ID!): [AgendaItem] agendaItemCategoriesByOrganization(organizationId: ID!): [AgendaCategory] + chatById(id: ID!): Chat! + chatsByUserId(id: ID!): [Chat] checkAuth: User! customDataByOrganization(organizationId: ID!): [UserCustomData!]! customFieldsByOrganization(id: ID!): [OrganizationCustomField] - directChatById(id: ID!): DirectChat - directChatsByUserID(id: ID!): [DirectChat] - directChatsMessagesByChatID(id: ID!): [DirectChatMessage] event(id: ID!): Event - eventVolunteersByEvent(id: ID!): [EventVolunteer] + eventsAttendedByUser(id: ID, orderBy: EventOrderByInput): [Event] eventsByOrganization(id: ID, orderBy: EventOrderByInput): [Event] - eventsByOrganizationConnection(first: Int, orderBy: EventOrderByInput, skip: Int, where: EventWhereInput): [Event!]! + eventsByOrganizationConnection(first: Int, orderBy: EventOrderByInput, skip: Int, upcomingOnly: Boolean, where: EventWhereInput): [Event!]! fundsByOrganization(orderBy: FundOrderByInput, organizationId: ID!, where: FundWhereInput): [Fund] getAgendaItem(id: ID!): AgendaItem getAgendaSection(id: ID!): AgendaSection @@ -1515,19 +1566,20 @@ type Query { getEventAttendee(eventId: ID!, userId: ID!): EventAttendee getEventAttendeesByEventId(eventId: ID!): [EventAttendee] getEventInvitesByUserId(userId: ID!): [EventAttendee!]! - getEventVolunteerGroups(where: EventVolunteerGroupWhereInput): [EventVolunteerGroup]! + getEventVolunteerGroups(orderBy: EventVolunteerGroupOrderByInput, where: EventVolunteerGroupWhereInput!): [EventVolunteerGroup]! + getEventVolunteers(orderBy: EventVolunteersOrderByInput, where: EventVolunteerWhereInput!): [EventVolunteer]! getFundById(id: ID!, orderBy: CampaignOrderByInput, where: CampaignWhereInput): Fund! getFundraisingCampaignPledgeById(id: ID!): FundraisingCampaignPledge! getFundraisingCampaigns(campaignOrderby: CampaignOrderByInput, pledgeOrderBy: PledgeOrderByInput, where: CampaignWhereInput): [FundraisingCampaign]! getNoteById(id: ID!): Note! getPledgesByUserId(orderBy: PledgeOrderByInput, userId: ID!, where: PledgeWhereInput): [FundraisingCampaignPledge] getPlugins: [Plugin] + getRecurringEvents(baseRecurringEventId: ID!): [Event] getUserTag(id: ID!): UserTag - getUserTagAncestors(id: ID!): [UserTag] getVenueByOrgId(first: Int, orderBy: VenueOrderByInput, orgId: ID!, skip: Int, where: VenueWhereInput): [Venue] + getVolunteerMembership(orderBy: VolunteerMembershipOrderByInput, where: VolunteerMembershipWhereInput!): [VolunteerMembership]! + getVolunteerRanks(orgId: ID!, where: VolunteerRankWhereInput!): [VolunteerRank]! getlanguage(lang_code: String!): [Translation] - groupChatById(id: ID!): GroupChat - groupChatsByUserId(id: ID!): [GroupChat] hasSubmittedFeedback(eventId: ID!, userId: ID!): Boolean isSampleOrganization(id: ID!): Boolean! joinedOrganizations(id: ID): [Organization] @@ -1628,12 +1680,15 @@ enum Status { } type Subscription { - directMessageChat: MessageChat - messageSentToDirectChat(userId: ID!): DirectChatMessage - messageSentToGroupChat(userId: ID!): GroupChatMessage + messageSentToChat(userId: ID!): ChatMessage onPluginUpdate: Plugin } +input TagActionsInput { + currentTagId: ID! + selectedTagIds: [ID!]! +} + scalar Time input ToggleUserTagAssignInput { @@ -1669,8 +1724,9 @@ input UpdateActionItemCategoryInput { } input UpdateActionItemInput { - allotedHours: Float + allottedHours: Float assigneeId: ID + assigneeType: String completionDate: Date dueDate: Date isCompleted: Boolean @@ -1740,16 +1796,16 @@ input UpdateEventInput { } input UpdateEventVolunteerGroupInput { - eventId: ID + description: String + eventId: ID! name: String volunteersRequired: Int } input UpdateEventVolunteerInput { - eventId: ID - isAssigned: Boolean - isInvited: Boolean - response: EventVolunteerResponse + assignments: [ID] + hasAccepted: Boolean + isPublic: Boolean } input UpdateFundCampaignInput { @@ -1827,6 +1883,8 @@ type User { email: EmailAddress! employmentStatus: EmploymentStatus eventAdmin: [Event] + eventsAttended: [Event] + file: File firstName: String! gender: Gender identifier: Int! @@ -1884,6 +1942,10 @@ input UserInput { selectedOrganization: ID! } +input UserNameWhereInput { + starts_with: String! +} + type UserNotAuthorizedAdminError implements Error { message: String! } @@ -1925,11 +1987,14 @@ type UserTag { """A field to get the mongodb object id identifier for this UserTag.""" _id: ID! + """A field to traverse the ancestor tags of this UserTag.""" + ancestorTags: [UserTag] + """ A connection field to traverse a list of UserTag this UserTag is a parent to. """ - childTags(after: String, before: String, first: PositiveInt, last: PositiveInt): UserTagsConnection + childTags(after: String, before: String, first: PositiveInt, last: PositiveInt, sortedBy: UserTagSortedByInput, where: UserTagWhereInput): UserTagsConnection """A field to get the name of this UserTag.""" name: String! @@ -1944,7 +2009,39 @@ type UserTag { A connection field to traverse a list of User this UserTag is assigned to. """ - usersAssignedTo(after: String, before: String, first: PositiveInt, last: PositiveInt): UsersConnection + usersAssignedTo(after: String, before: String, first: PositiveInt, last: PositiveInt, sortedBy: UserTagUsersAssignedToSortedByInput, where: UserTagUsersAssignedToWhereInput): UsersConnection + + """ + A connection field to traverse a list of Users this UserTag is not assigned + to, to see and select among them and assign this tag. + """ + usersToAssignTo(after: String, before: String, first: PositiveInt, last: PositiveInt, where: UserTagUsersToAssignToWhereInput): UsersConnection +} + +input UserTagNameWhereInput { + starts_with: String! +} + +input UserTagSortedByInput { + id: SortedByOrder! +} + +input UserTagUsersAssignedToSortedByInput { + id: SortedByOrder! +} + +input UserTagUsersAssignedToWhereInput { + firstName: UserNameWhereInput + lastName: UserNameWhereInput +} + +input UserTagUsersToAssignToWhereInput { + firstName: UserNameWhereInput + lastName: UserNameWhereInput +} + +input UserTagWhereInput { + name: UserTagNameWhereInput } """A default connection on the UserTag type.""" @@ -2037,6 +2134,53 @@ input VenueWhereInput { name_starts_with: String } +type VolunteerMembership { + _id: ID! + createdAt: DateTime! + createdBy: User + event: Event! + group: EventVolunteerGroup + status: String! + updatedAt: DateTime! + updatedBy: User + volunteer: EventVolunteer! +} + +input VolunteerMembershipInput { + event: ID! + group: ID + status: String! + userId: ID! +} + +enum VolunteerMembershipOrderByInput { + createdAt_ASC + createdAt_DESC +} + +input VolunteerMembershipWhereInput { + eventId: ID + eventTitle: String + filter: String + groupId: ID + status: String + userId: ID + userName: String +} + +type VolunteerRank { + hoursVolunteered: Float! + rank: Int! + user: User! +} + +input VolunteerRankWhereInput { + limit: Int + nameContains: String + orderBy: String! + timeFrame: String! +} + enum WeekDays { FRIDAY MONDAY @@ -2047,22 +2191,14 @@ enum WeekDays { WEDNESDAY } -input createChatInput { +input chatInput { + image: String + isGroup: Boolean! + name: String organizationId: ID userIds: [ID!]! } -type createDirectChatPayload { - directChat: DirectChat - userErrors: [CreateDirectChatError!]! -} - -input createGroupChatInput { - organizationId: ID! - title: String! - userIds: [ID!]! -} - input createUserFamilyInput { title: String! userIds: [ID!]! diff --git a/setup.ts b/setup.ts index 3d31dd86ba..c5e5a9cc56 100644 --- a/setup.ts +++ b/setup.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-imports */ import * as cryptolib from "crypto"; import dotenv from "dotenv"; import fs from "fs"; diff --git a/src/REST/controllers/mutation/createPost.ts b/src/REST/controllers/mutation/createPost.ts new file mode 100644 index 0000000000..4a59978317 --- /dev/null +++ b/src/REST/controllers/mutation/createPost.ts @@ -0,0 +1,262 @@ +import type { Response } from "express"; +import mongoose from "mongoose"; +import { + INTERNAL_SERVER_ERROR, + LENGTH_VALIDATION_ERROR, + ORGANIZATION_NOT_FOUND_ERROR, + PLEASE_PROVIDE_TITLE, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_AUTHORIZED_TO_PIN, + USER_NOT_FOUND_ERROR, + USER_NOT_MEMBER_FOR_ORGANIZATION, +} from "../../../constants"; +import { errors, requestContext } from "../../../libraries"; +import { isValidString } from "../../../libraries/validators/validateString"; +import type { + InterfaceAppUserProfile, + InterfaceOrganization, + InterfaceUser, +} from "../../../models"; +import { AppUserProfile, Organization, Post, User } from "../../../models"; +import { cacheAppUserProfile } from "../../../services/AppUserProfileCache/cacheAppUserProfile"; +import { findAppUserProfileCache } from "../../../services/AppUserProfileCache/findAppUserProfileCache"; +import { cacheOrganizations } from "../../../services/OrganizationCache/cacheOrganizations"; +import { findOrganizationsInCache } from "../../../services/OrganizationCache/findOrganizationsInCache"; +import { cachePosts } from "../../../services/PostCache/cachePosts"; +import { cacheUsers } from "../../../services/UserCache/cacheUser"; +import { findUserInCache } from "../../../services/UserCache/findUserInCache"; +import type { InterfaceAuthenticatedRequest } from "../../../middleware"; +import { uploadFile } from "../../services/file"; + +interface InterfaceCreatePostRequestBody { + organizationId: string; + title?: string; + text: string; + pinned?: boolean; +} + +/** + * Controller for creating posts within organizations + */ + +/** + * Creates a new post within an organization + * async + * function - createPost + * @param req - Express request object with authenticated user + * @param res - Express response object + * @throws NotFoundError - When user or organization is not found + * @throws UnauthorizedError - When user is not authorized or lacks permissions + * @throws InputValidationError - When title or text validation fails + * @returns Promise - Responds with created post or error + * + * Description + * This controller handles post creation with the following features: + * - Validates user membership in the organization + * - Supports file attachments + * - Handles post pinning with proper authorization + * - Validates title and text length + * - Caches created posts and updated organizations + * + * Request body expects: + * ```typescript + * { + * organizationId: string; + * title?: string; + * text: string; + * pinned?: boolean; + * } + * ``` + */ +export const createPost = async ( + req: InterfaceAuthenticatedRequest, + res: Response, +): Promise => { + const userId = req.userId; + const { + organizationId, + title, + text, + pinned, + }: InterfaceCreatePostRequestBody = req.body; + + try { + // Get the current user + let currentUser: InterfaceUser | null; + const userFoundInCache = await findUserInCache([userId as string]); + currentUser = userFoundInCache[0]; + if (currentUser === null) { + currentUser = await User.findOne({ _id: userId }).lean(); + if (currentUser !== null) { + await cacheUsers([currentUser]); + } + } + + // Check if currentUser exists + if (!currentUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + // Get current user's app profile + let currentUserAppProfile: InterfaceAppUserProfile | null; + const appUserProfileFoundInCache = await findAppUserProfileCache([ + currentUser.appUserProfileId?.toString(), + ]); + currentUserAppProfile = appUserProfileFoundInCache[0]; + if (currentUserAppProfile === null) { + currentUserAppProfile = await AppUserProfile.findOne({ + userId: currentUser._id, + }).lean(); + if (currentUserAppProfile !== null) { + await cacheAppUserProfile([currentUserAppProfile]); + } + } + + if (!currentUserAppProfile) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Get the organization + let organization: InterfaceOrganization | null; + const organizationFoundInCache = await findOrganizationsInCache([ + organizationId, + ]); + organization = organizationFoundInCache[0]; + if (organization === null) { + organization = await Organization.findOne({ _id: organizationId }).lean(); + if (organization) { + await cacheOrganizations([organization]); + } + } + + if (!organization) { + throw new errors.NotFoundError( + requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), + ORGANIZATION_NOT_FOUND_ERROR.CODE, + ORGANIZATION_NOT_FOUND_ERROR.PARAM, + ); + } + + // Check if user is a member of the organization or a super admin + const isSuperAdmin = currentUserAppProfile.isSuperAdmin; + const currentUserIsOrganizationMember = organization.members.some( + (memberId) => + new mongoose.Types.ObjectId(memberId?.toString()).equals(userId), + ); + + if (!currentUserIsOrganizationMember && !isSuperAdmin) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE), + USER_NOT_MEMBER_FOR_ORGANIZATION.CODE, + USER_NOT_MEMBER_FOR_ORGANIZATION.PARAM, + ); + } + + let fileUploadResponse; + if (req.file) { + fileUploadResponse = await uploadFile(req, res); + } + + // Validate title and pinned status + if (!title && pinned) { + throw new errors.InputValidationError( + requestContext.translate(PLEASE_PROVIDE_TITLE.MESSAGE), + PLEASE_PROVIDE_TITLE.CODE, + ); + } + + // Validate title and text length + if (title) { + const validationResultTitle = isValidString(title, 256); + if (!validationResultTitle.isLessThanMaxLength) { + throw new errors.InputValidationError( + requestContext.translate( + `${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, + ), + LENGTH_VALIDATION_ERROR.CODE, + ); + } + } + + const validationResultText = isValidString(text, 500); + if (!validationResultText.isLessThanMaxLength) { + throw new errors.InputValidationError( + requestContext.translate( + `${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, + ), + LENGTH_VALIDATION_ERROR.CODE, + ); + } + + // Check permissions for pinning + if (pinned) { + const currentUserIsOrganizationAdmin = + currentUserAppProfile.adminFor.some((orgId) => + new mongoose.Types.ObjectId(orgId?.toString()).equals(organizationId), + ); + + if ( + !(currentUserAppProfile.isSuperAdmin || currentUserIsOrganizationAdmin) + ) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_TO_PIN.MESSAGE), + USER_NOT_AUTHORIZED_TO_PIN.CODE, + USER_NOT_AUTHORIZED_TO_PIN.PARAM, + ); + } + } + + // Create the post + const createdPost = await Post.create({ + title, + text, + pinned: pinned || false, + creatorId: userId, + organization: organizationId, + file: fileUploadResponse?._id, + }); + + if (createdPost !== null) { + await cachePosts([createdPost]); + } + + // Update organization if post is pinned + if (pinned) { + const updatedOrganization = await Organization.findOneAndUpdate( + { _id: organizationId }, + { + $push: { + pinnedPosts: createdPost._id, + }, + }, + { + new: true, + }, + ); + + await cacheOrganizations([updatedOrganization as InterfaceOrganization]); + } + + // Send response + res.status(201).json({ + post: createdPost, + }); + } catch (error) { + console.error(error); + if (error instanceof Error) { + res.status(500).json({ error: error.message }); + } else { + res.status(500).json({ + error: requestContext.translate(INTERNAL_SERVER_ERROR.MESSAGE), + }); + } + } +}; diff --git a/src/REST/controllers/mutation/index.ts b/src/REST/controllers/mutation/index.ts new file mode 100644 index 0000000000..d39f54f2c9 --- /dev/null +++ b/src/REST/controllers/mutation/index.ts @@ -0,0 +1,2 @@ +export * from "./createPost"; +export * from "./updatePost"; diff --git a/src/REST/controllers/mutation/updatePost.ts b/src/REST/controllers/mutation/updatePost.ts new file mode 100644 index 0000000000..400ff5e084 --- /dev/null +++ b/src/REST/controllers/mutation/updatePost.ts @@ -0,0 +1,246 @@ +import type { Response } from "express"; +import { Types } from "mongoose"; +import { + INTERNAL_SERVER_ERROR, + LENGTH_VALIDATION_ERROR, + PLEASE_PROVIDE_TITLE, + POST_NEEDS_TO_BE_PINNED, + POST_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../constants"; +import { errors, requestContext } from "../../../libraries"; +import { isValidString } from "../../../libraries/validators/validateString"; +import type { + InterfaceAppUserProfile, + InterfacePost, + InterfaceUser, +} from "../../../models"; +import { AppUserProfile, Post, User } from "../../../models"; +import { cachePosts } from "../../../services/PostCache/cachePosts"; +import { findPostsInCache } from "../../../services/PostCache/findPostsInCache"; +import { findUserInCache } from "../../../services/UserCache/findUserInCache"; +import { cacheUsers } from "../../../services/UserCache/cacheUser"; +import { findAppUserProfileCache } from "../../../services/AppUserProfileCache/findAppUserProfileCache"; +import { cacheAppUserProfile } from "../../../services/AppUserProfileCache/cacheAppUserProfile"; +import type { InterfaceAuthenticatedRequest } from "../../../middleware"; +import { deleteFile, uploadFile } from "../../services/file"; + +interface InterfaceUpdatePostRequestBody { + title?: string; + text?: string; + pinned?: boolean; +} + +/** + * Controller for updating existing posts within organizations + */ + +/** + * Updates an existing post + * async + * function - updatePost + * @param req - Express request object with authenticated user + * @param res - Express response object + * @throws NotFoundError - When user or post is not found + * @throws UnauthorizedError - When user lacks permissions to update the post + * @throws InputValidationError - When title/text validation fails or pinned status requirements aren't met + * @returns Promise - Responds with updated post or error + * + * Description + * This controller handles post updates with the following features: + * - Validates user permissions (creator, organization admin, or super admin) + * - Supports file attachment updates with cleanup of old files + * - Enforces business rules for pinned posts and titles + * - Validates content length restrictions + * - Maintains cache consistency + * + * Request body expects: + * ```typescript + * { + * title?: string; + * text?: string; + * pinned?: boolean; + * } + * ``` + * + * Authorization Rules: + * - Post creator can edit their own posts + * - Organization admins can edit posts in their organizations + * - Super admins can edit any post + */ + +export const updatePost = async ( + req: InterfaceAuthenticatedRequest, + res: Response, +): Promise => { + const userId = req.userId; + const postId = req.params.id; + const { title, text, pinned }: InterfaceUpdatePostRequestBody = req.body; + + try { + // Get the current user + let currentUser: InterfaceUser | null; + const userFoundInCache = await findUserInCache([userId as string]); + currentUser = userFoundInCache[0]; + if (currentUser === null) { + currentUser = await User.findOne({ _id: userId }).lean(); + if (currentUser !== null) { + await cacheUsers([currentUser]); + } + } + + if (!currentUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + // Get current user's app profile + let currentUserAppProfile: InterfaceAppUserProfile | null; + const appUserProfileFoundInCache = await findAppUserProfileCache([ + currentUser.appUserProfileId?.toString(), + ]); + currentUserAppProfile = appUserProfileFoundInCache[0]; + if (currentUserAppProfile === null) { + currentUserAppProfile = await AppUserProfile.findOne({ + userId: currentUser._id, + }).lean(); + if (currentUserAppProfile !== null) { + await cacheAppUserProfile([currentUserAppProfile]); + } + } + + if (!currentUserAppProfile) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Get the post + let post: InterfacePost | null; + const postFoundInCache = await findPostsInCache([postId]); + post = postFoundInCache[0]; + if (post === null) { + post = await Post.findOne({ _id: postId }).populate("file").lean(); + if (post !== null) { + await cachePosts([post]); + } + } + + if (!post) { + throw new errors.NotFoundError( + requestContext.translate(POST_NOT_FOUND_ERROR.MESSAGE), + POST_NOT_FOUND_ERROR.CODE, + POST_NOT_FOUND_ERROR.PARAM, + ); + } + + // Check if the user has the right to update the post + const currentUserIsPostCreator = post.creatorId.equals(userId); + const isSuperAdmin = currentUserAppProfile.isSuperAdmin; + const isAdminOfPostOrganization = currentUserAppProfile?.adminFor.some( + (orgID) => + orgID && + new Types.ObjectId(orgID?.toString()).equals(post?.organization), + ); + + if ( + !currentUserIsPostCreator && + !isAdminOfPostOrganization && + !isSuperAdmin + ) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Handle file upload and cleanup + let fileId: string | undefined; + const oldFileId = post.file?._id?.toString(); + const oldObjectKey = post.file.metadata?.objectKey; + + if (req.file) { + // Upload new file + const response = await uploadFile(req, res); + fileId = response._id?.toString(); + + // Clean up old file if it exists + if (oldFileId && oldObjectKey) { + await deleteFile(oldObjectKey, oldFileId); + } + } + + // Validate title and pinned status + if (title && !post.pinned) { + throw new errors.InputValidationError( + requestContext.translate(POST_NEEDS_TO_BE_PINNED.MESSAGE), + POST_NEEDS_TO_BE_PINNED.CODE, + ); + } else if (!title && post.pinned) { + throw new errors.InputValidationError( + requestContext.translate(PLEASE_PROVIDE_TITLE.MESSAGE), + PLEASE_PROVIDE_TITLE.CODE, + ); + } + + // Validate input lengths + if (title) { + const validationResultTitle = isValidString(title, 256); + if (!validationResultTitle.isLessThanMaxLength) { + throw new errors.InputValidationError( + requestContext.translate( + `${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, + ), + LENGTH_VALIDATION_ERROR.CODE, + ); + } + } + + if (text) { + const validationResultText = isValidString(text, 500); + if (!validationResultText.isLessThanMaxLength) { + throw new errors.InputValidationError( + requestContext.translate( + `${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, + ), + LENGTH_VALIDATION_ERROR.CODE, + ); + } + } + + const updatedPost = await Post.findOneAndUpdate( + { _id: postId }, + { + ...(title && { title }), + ...(text && { text }), + ...(pinned !== undefined && { pinned }), + ...(fileId && { file: fileId }), + }, + { new: true }, + ).lean(); + + if (updatedPost !== null) { + await cachePosts([updatedPost]); + } + + res.status(200).json({ + post: updatedPost, + }); + } catch (error) { + console.error(error); + if (error instanceof Error) { + res.status(500).json({ error: error.message }); + } else { + res.status(500).json({ + error: requestContext.translate(INTERNAL_SERVER_ERROR.MESSAGE), + }); + } + } +}; diff --git a/src/REST/controllers/query/getFile.ts b/src/REST/controllers/query/getFile.ts new file mode 100644 index 0000000000..171c53ca48 --- /dev/null +++ b/src/REST/controllers/query/getFile.ts @@ -0,0 +1,40 @@ +import type { Request, Response } from "express"; +import { s3Client, BUCKET_NAME } from "../../../config/minio"; +import { GetObjectCommand } from "@aws-sdk/client-s3"; +import type { Readable } from "stream"; + +/** + * Middleware to retrieve a file from S3 storage. + * + * This function retrieves a file from an S3-compatible storage service using the provided key from the request parameters. + * If the file is found, it streams the file's content back to the client with the appropriate content type. + * If an error occurs during the retrieval, it logs the error and sends a 500 status code response. + * + * @param req - The Express request object, containing the key for the file in the parameters. + * @param res - The Express response object used to send the file back to the client. + * + * @returns A promise that resolves to void. The function either streams the file or sends an error response. + * + * @example + * ```typescript + * app.get("/file/:key*", getFile); + * ``` + */ +export const getFile = async (req: Request, res: Response): Promise => { + const key = req.params[0]; + const command = new GetObjectCommand({ + Bucket: BUCKET_NAME, + Key: key, + }); + + try { + const data = await s3Client.send(command); + const stream = data.Body as Readable; + res.setHeader("Content-Type", data.ContentType as string); + res.setHeader("Cross-Origin-Resource-Policy", "same-site"); + stream.pipe(res); + } catch (error) { + console.error("Error fetching file:", error); + res.status(500).send("Error occurred while fetching file"); + } +}; diff --git a/src/REST/controllers/query/index.ts b/src/REST/controllers/query/index.ts new file mode 100644 index 0000000000..1a94d7580d --- /dev/null +++ b/src/REST/controllers/query/index.ts @@ -0,0 +1 @@ +export * from "./getFile"; diff --git a/src/REST/routes/index.ts b/src/REST/routes/index.ts new file mode 100644 index 0000000000..54b74a44cf --- /dev/null +++ b/src/REST/routes/index.ts @@ -0,0 +1,31 @@ +// routes/fileRoutes.ts +import express from "express"; + +import { getFile } from "../controllers/query/getFile"; +import { createPost, updatePost } from "../controllers/mutation"; + +import { isAuthMiddleware } from "../../middleware"; +import { fileUpload } from "../../middleware/fileUpload"; + +const router = express.Router(); + +// Routes + +// Routes +/** + * Retrieves a file by its key. + * isAuthMiddleware - Authenticates the user. + * getFile - Handles fetching the requested file. + */ +router.get("/file/*", getFile); + +router.post("/create-post", isAuthMiddleware, fileUpload("file"), createPost); + +router.post( + "/update-post/:id", + isAuthMiddleware, + fileUpload("file"), + updatePost, +); + +export default router; diff --git a/src/REST/services/file/createFile.ts b/src/REST/services/file/createFile.ts new file mode 100644 index 0000000000..21586598a9 --- /dev/null +++ b/src/REST/services/file/createFile.ts @@ -0,0 +1,55 @@ +import { BUCKET_NAME } from "../../../config/minio"; +import { BASE_URL } from "../../../constants"; +import type { InterfaceFile } from "../../../models"; +import { File } from "../../../models"; +import type { InterfaceUploadResult } from "../minio"; + +/** + * Creates or updates a file document in the database based on the upload result. + * + * This function checks if a file with the same hash already exists. If it does, the reference count of the file is incremented. + * If not, a new file document is created and saved to the database. + * + * @param uploadResult - The result from the file upload containing the hash, object key, and hash algorithm. + * @param originalname - The original name of the uploaded file. + * @param mimetype - The MIME type of the uploaded file. + * @param size - The size of the uploaded file in bytes. + * @returns A promise that resolves to the created or updated file document. + * + * @example + * ```typescript + * const file = await createFile(uploadResult, "image.png", "image/png", 2048); + * console.log(file); + * ``` + */ +export const createFile = async ( + uploadResult: InterfaceUploadResult, + originalname: string, + mimetype: string, + size: number, +): Promise => { + const existingFile = await File.findOne({ "hash.value": uploadResult.hash }); + + if (existingFile) { + existingFile.referenceCount += 1; + await existingFile.save(); + return existingFile; + } + + const newFileDoc = await File.create({ + fileName: originalname, + mimeType: mimetype, + size: size, + hash: { + value: uploadResult.hash, + algorithm: uploadResult.hashAlgorithm, + }, + uri: `${BASE_URL}api/file/${uploadResult.objectKey}`, + metadata: { + objectKey: uploadResult.objectKey, + bucketName: BUCKET_NAME, + }, + }); + + return newFileDoc; +}; diff --git a/src/REST/services/file/deleteFile.ts b/src/REST/services/file/deleteFile.ts new file mode 100644 index 0000000000..363da6fcd9 --- /dev/null +++ b/src/REST/services/file/deleteFile.ts @@ -0,0 +1,35 @@ +import { File } from "../../../models"; +import { deleteFile as deleteFileFromBucket } from "../minio"; +import { BUCKET_NAME } from "../../../config/minio"; + +export const deleteFile = async ( + objectKey: string, + fileId: string, +): Promise<{ success: boolean; message: string }> => { + try { + const file = await File.findOne({ + _id: fileId, + "metadata.objectKey": objectKey, + }); + + if (!file) { + return { success: false, message: "File not found." }; + } + + if (file.referenceCount > 1) { + file.referenceCount -= 1; + await file.save(); + return { + success: true, + message: "File reference count decreased successfully", + }; + } + + await File.deleteOne({ _id: file.id }); + await deleteFileFromBucket(BUCKET_NAME as string, objectKey); + return { success: true, message: "File deleted successfully" }; + } catch (error) { + console.error("Error deleting file:", error); + return { success: false, message: "Error occurred while deleting file" }; + } +}; diff --git a/src/REST/services/file/index.ts b/src/REST/services/file/index.ts new file mode 100644 index 0000000000..e614f3ec1e --- /dev/null +++ b/src/REST/services/file/index.ts @@ -0,0 +1,3 @@ +export { createFile } from "./createFile"; +export { deleteFile } from "./deleteFile"; +export { uploadFile } from "./uploadFile"; diff --git a/src/REST/services/file/uploadFile.ts b/src/REST/services/file/uploadFile.ts new file mode 100644 index 0000000000..36408b8b05 --- /dev/null +++ b/src/REST/services/file/uploadFile.ts @@ -0,0 +1,79 @@ +import type { Request, Response } from "express"; + +import { uploadMedia } from "../minio"; +import { createFile } from "./createFile"; +import { BUCKET_NAME } from "../../../config/minio"; + +import { isValidMimeType } from "../../../utilities/isValidMimeType"; + +import type { InterfaceFile } from "../../../models"; +import { errors, requestContext } from "../../../libraries"; +import { + FILE_NOT_FOUND, + INTERNAL_SERVER_ERROR, + INVALID_FILE_TYPE, +} from "../../../constants"; + +export interface InterfaceUploadedFileResponse extends Partial { + objectKey: string; +} + +/** + * Handles file upload. + * @param req - The HTTP request object containing the file. + * @param res - The HTTP response object used to send the response. + * @throws Error - Throws an error if no file is uploaded or if the file type is invalid. + * @returns UploadedFileResponse - The response containing file ID and object key. + */ +export const uploadFile = async ( + req: Request, + res: Response, +): Promise => { + if (!req.file) { + res + .status(400) + .json({ error: requestContext.translate(FILE_NOT_FOUND.MESSAGE) }); + throw new errors.InputValidationError( + requestContext.translate(FILE_NOT_FOUND.MESSAGE), + FILE_NOT_FOUND.CODE, + ); + } + + const { mimetype, originalname, buffer, size } = req.file; + + if (!isValidMimeType(mimetype)) { + throw new errors.InputValidationError( + requestContext.translate(INVALID_FILE_TYPE.MESSAGE), + INVALID_FILE_TYPE.CODE, + ); + } + + try { + const contentType = { ContentType: mimetype }; + const uploadedFile = await uploadMedia( + BUCKET_NAME as string, + buffer, + originalname, + contentType, + ); + const fileDoc = await createFile( + uploadedFile, + originalname, + mimetype, + size, + ); + + return { + uri: fileDoc.uri, + _id: fileDoc._id, + visibility: fileDoc.visibility, + objectKey: fileDoc.metadata.objectKey, + }; + } catch (error) { + console.error("Error", error); + throw new errors.InternalServerError( + requestContext.translate(INTERNAL_SERVER_ERROR.MESSAGE), + INTERNAL_SERVER_ERROR.CODE, + ); + } +}; diff --git a/src/REST/services/minio/index.ts b/src/REST/services/minio/index.ts new file mode 100644 index 0000000000..e9d37beb65 --- /dev/null +++ b/src/REST/services/minio/index.ts @@ -0,0 +1,130 @@ +// Import third-party modules +import crypto from "crypto"; +import path from "path"; + +// Import AWS SDK S3 client and commands +import { + DeleteObjectCommand, + HeadObjectCommand, + PutObjectCommand, +} from "@aws-sdk/client-s3"; +import type { DeleteObjectCommandOutput } from "@aws-sdk/client-s3"; + +// Import project configuration +import { s3Client } from "../../../config/minio"; + +export interface InterfaceUploadResult { + exists: boolean; + objectKey: string; + hash: string; + hashAlgorithm: string; +} + +/** + * Uploads a media file to a specified S3 bucket, calculating its hash for naming and uniqueness. + * + * The `uploadMedia` function calculates the SHA-256 hash of the provided buffer to generate a unique object key. + * It first checks if a file with the same hash already exists in the bucket using the `HeadObjectCommand`. + * If the file does not exist, it uploads the file using the `PutObjectCommand`. It supports both image and video uploads + * by assigning appropriate prefixes to the object key. + * + * @param bucketName - The name of the S3 bucket where the file will be uploaded. + * @param buffer - The file content as a buffer. + * @param originalname - The original file name, used to determine the file extension. + * @param contentType - An object specifying the content type of the file. + * @returns A promise that resolves to an object containing the file's existence status, object key, hash, and hash algorithm. + * + * @example + * ```typescript + * const result = await uploadMedia("my-bucket", fileBuffer, "image.png", { ContentType: "image/png" }); + * console.log(result); + * ``` + */ +export const uploadMedia = async ( + bucketName: string, + buffer: Buffer, + originalname: string, + contentType: { ContentType: string }, +): Promise => { + const hash = crypto.createHash("sha256").update(buffer).digest("hex"); + const fileExtension = path.extname(originalname); + + let prefix = ""; + if (contentType.ContentType.startsWith("image/")) { + prefix = "image/"; + } else if (contentType.ContentType.startsWith("video/")) { + prefix = "video/"; + } + + const objectKey = `${prefix}${hash}${fileExtension}`; + + const headParams = { + Bucket: bucketName, + Key: objectKey, + }; + const headCommand = new HeadObjectCommand(headParams); + + try { + await s3Client.send(headCommand); + return { exists: true, objectKey, hash, hashAlgorithm: "sha256" }; + } catch (error: unknown) { + if ( + error instanceof Error && + "name" in error && + error.name === "NotFound" + ) { + const params = { + Bucket: bucketName, + Key: objectKey, + Body: buffer, + ...contentType, + }; + + try { + const command = new PutObjectCommand(params); + await s3Client.send(command); + return { exists: false, objectKey, hash, hashAlgorithm: "sha256" }; + } catch (uploadError: unknown) { + console.error("Error uploading the file:", uploadError); + throw uploadError; + } + } else { + console.error("Error checking file existence:", error); + throw error; + } + } +}; + +/** + * Deletes a file from a specified S3 bucket. + * + * The `deleteFile` function deletes an object in an S3 bucket using the `DeleteObjectCommand`. + * If an error occurs during the deletion process, it logs the error and rethrows it. + * + * @param bucketName - The name of the S3 bucket from which the file will be deleted. + * @param objectKey - The key of the object to be deleted in the S3 bucket. + * @returns A promise that resolves to the output of the `DeleteObjectCommand`. + * + * @example + * ```typescript + * const response = await deleteFile("my-bucket", "image123.png"); + * console.log(response); + * ``` + */ +export const deleteFile = async ( + bucketName: string, + objectKey: string, +): Promise => { + const params = { + Bucket: bucketName, + Key: objectKey, + }; + const command = new DeleteObjectCommand(params); + try { + const response = await s3Client.send(command); + return response; + } catch (error) { + console.error("Error deleting file:", error); + throw error; + } +}; diff --git a/src/REST/types/index.ts b/src/REST/types/index.ts new file mode 100644 index 0000000000..4725dcca52 --- /dev/null +++ b/src/REST/types/index.ts @@ -0,0 +1,9 @@ +/** + * Allowed MIME types for files. + */ +export type FileMimeType = + | "image/jpeg" + | "image/png" + | "image/gif" + | "image/webp" + | "video/mp4"; diff --git a/src/app.ts b/src/app.ts index a5571597a4..e8e0f4eb86 100644 --- a/src/app.ts +++ b/src/app.ts @@ -6,19 +6,21 @@ import { express as voyagerMiddleware } from "graphql-voyager/middleware"; import helmet from "helmet"; import i18n from "i18n"; import requestLogger from "morgan"; -import path from "path"; import { appConfig } from "./config"; import { requestContext, requestTracing, stream } from "./libraries"; -import graphqlUploadExpress from "graphql-upload/graphqlUploadExpress.mjs"; +import routes from "./REST/routes"; + +import * as enLocale from "../locales/en.json"; +import * as hiLocale from "../locales/hi.json"; +import * as zhLocale from "../locales/zh.json"; +import * as spLocale from "../locales/sp.json"; +import * as frLocale from "../locales/fr.json"; const app = express(); // Middleware for tracing requests app.use(requestTracing.middleware()); -// Initialize i18n for internationalization -app.use(i18n.init); - // Rate limiting middleware to prevent abuse const apiLimiter = rateLimit({ windowMs: 60 * 60 * 1000, // 1 hour window @@ -27,7 +29,6 @@ const apiLimiter = rateLimit({ }); app.use(apiLimiter); -// eslint-disable-next-line @typescript-eslint/no-unused-vars const corsOptions: cors.CorsOptions = { origin: (origin, next) => { if (process.env.NODE_ENV === "development") { @@ -42,17 +43,18 @@ const corsOptions: cors.CorsOptions = { } next(new Error("Unauthorized")); // Reject other origins }, + optionsSuccessStatus: 200, }; // Configure i18n settings i18n.configure({ directory: `${__dirname}/../locales`, staticCatalog: { - en: require("../locales/en.json"), - hi: require("../locales/hi.json"), - zh: require("../locales/zh.json"), - sp: require("../locales/sp.json"), - fr: require("../locales/fr.json"), + en: enLocale, + hi: hiLocale, + zh: zhLocale, + sp: spLocale, + fr: frLocale, }, queryParameter: "lang", defaultLocale: appConfig.defaultLocale, @@ -73,20 +75,11 @@ app.use( // Sanitize data to prevent MongoDB operator injection app.use(mongoSanitize()); -app.use(cors()); - -// Serve static files with Cross-Origin-Resource-Policy header set -app.use("/images", (req, res, next) => { - res.setHeader("Cross-Origin-Resource-Policy", "cross-origin"); - next(); -}); +app.use(cors(corsOptions)); // Parse JSON requests with a size limit of 50mb app.use(express.json({ limit: "50mb" })); -// Handle file uploads using graphql-upload -app.use(graphqlUploadExpress()); - // Parse URL-encoded requests with a size limit of 50mb app.use(express.urlencoded({ limit: "50mb", extended: true })); @@ -100,13 +93,11 @@ app.use( ), ); -// Serve static files for images and videos -app.use("/images", express.static(path.join(__dirname, "./../images"))); -app.use("/videos", express.static(path.join(__dirname, "./../videos"))); - // Middleware for managing request context (e.g., user session) app.use(requestContext.middleware()); +app.use("/api", routes); + // Enable GraphQL Voyager visualization in development if (process.env.NODE_ENV !== "production") { app.use("/voyager", voyagerMiddleware({ endpointUrl: "/graphql" })); diff --git a/src/config/minio/index.ts b/src/config/minio/index.ts new file mode 100644 index 0000000000..64fc4911d7 --- /dev/null +++ b/src/config/minio/index.ts @@ -0,0 +1,47 @@ +import { S3Client } from "@aws-sdk/client-s3"; + +/** + * Initializes and exports an S3 client instance using AWS SDK for connecting to MinIO storage. + * + * The `s3Client` is an instance of the AWS S3 client configured to interact with a MinIO storage service. + * The client uses custom endpoint, credentials, and region details from environment variables to + * establish the connection. It also forces path-style access to ensure compatibility with MinIO. + * + * **Environment Variables:** + * - `MINIO_ENDPOINT`: The MinIO storage endpoint URL. + * - `MINIO_ROOT_USER`: The access key ID for the MinIO instance. + * - `MINIO_ROOT_PASSWORD`: The secret access key for the MinIO instance. + * - `MINIO_BUCKET`: The default bucket name in MinIO. + * + * @example + * ```typescript + * import { s3Client } from './path/to/file'; + * + * // Example usage + * const data = await s3Client.send(new ListBucketsCommand({})); + * console.log(data.Buckets); + * ``` + * + * @returns S3Client - an instance of the AWS S3 client configured for MinIO storage. + */ +export const s3Client = new S3Client({ + endpoint: process.env.MINIO_ENDPOINT, + credentials: { + accessKeyId: process.env.MINIO_ROOT_USER as string, + secretAccessKey: process.env.MINIO_ROOT_PASSWORD as string, + }, + region: process.env.MNIO_REGION, + forcePathStyle: true, +}); + +/** + * The name of the bucket used in the MinIO storage, defined via an environment variable. + * + * @example + * ```typescript + * console.log(BUCKET_NAME); // Logs the bucket name from the environment + * ``` + * + * @returns The name of the MinIO bucket. + */ +export const BUCKET_NAME = process.env.MINIO_BUCKET; diff --git a/src/config/multer/index.ts b/src/config/multer/index.ts new file mode 100644 index 0000000000..ce13a2a9d4 --- /dev/null +++ b/src/config/multer/index.ts @@ -0,0 +1,69 @@ +import multer from "multer"; +import { + VIDEO_SIZE_LIMIT, + ALLOWED_IMAGE_TYPES, + ALLOWED_VIDEO_TYPES, + INVALID_FILE_TYPE, +} from "../../constants"; +import type { Request } from "express"; +import { errors, requestContext } from "../../libraries"; + +/** + * File filter function for multer. + * + * This function checks the MIME type of the uploaded file against allowed image and video types. + * If the file type is valid, it calls the callback with `true`. Otherwise, it calls the callback + * with an error message. + * + * @param req - The Express request object. + * @param file - The file being uploaded. + * @param cb - The callback function to indicate if the file is accepted or rejected. + * + * @example + * ```typescript + * fileFilter(req, file, cb); + * ``` + */ +export const fileFilter = ( + req: Request, + file: Express.Multer.File, + cb: multer.FileFilterCallback, +): void => { + if (ALLOWED_IMAGE_TYPES.includes(file.mimetype)) { + cb(null, true); + } else if (ALLOWED_VIDEO_TYPES.includes(file.mimetype)) { + cb(null, true); + } else { + cb( + new errors.InvalidFileTypeError( + requestContext.translate(INVALID_FILE_TYPE.MESSAGE), + INVALID_FILE_TYPE.CODE, + INVALID_FILE_TYPE.PARAM, + ), + ); + } +}; + +/** + * Multer upload configuration. + * + * This configuration sets up multer to use memory storage, applies the file filter, + * and sets a file size limit for uploads. + * + * @returns A multer instance configured for handling uploads. + * + * @example + * ```typescript + * const uploadMiddleware = upload.single("file"); + * app.post("/upload", uploadMiddleware, (req, res) => { + * res.send("File uploaded successfully!"); + * }); + * ``` + */ +export const upload = multer({ + storage: multer.memoryStorage(), + fileFilter, + limits: { + fileSize: VIDEO_SIZE_LIMIT + 2, + }, +}); diff --git a/src/constants.ts b/src/constants.ts index fab3f2b12d..b30914dd5d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -43,6 +43,13 @@ export const AGENDA_CATEGORY_NOT_FOUND_ERROR = Object.freeze({ PARAM: "agendaCategory", }); +export const APP_USER_PROFILE_NOT_FOUND_ERROR = Object.freeze({ + DESC: "appUserProfile not found", + CODE: "appUserProfile.notFound", + MESSAGE: "appUserProfile.notFound", + PARAM: "appUserProfile", +}); + export const BASE_RECURRING_EVENT_NOT_FOUND = Object.freeze({ DESC: "Base Recurring Event not found", CODE: "baseRecurringEvent.notFound", @@ -57,6 +64,20 @@ export const CHAT_NOT_FOUND_ERROR = Object.freeze({ PARAM: "chat", }); +export const MESSAGE_NOT_FOUND_ERROR = Object.freeze({ + DESC: "Message not found", + CODE: "message.notFound", + MESSAGE: "message.notFound", + PARAM: "message", +}); + +export const COMMUNITY_NOT_FOUND_ERROR = Object.freeze({ + DESC: "Community not found", + CODE: "community.notFound", + MESSAGE: "community.notFound", + PARAM: "community", +}); + export const VENUE_ALREADY_EXISTS_ERROR = Object.freeze({ DESC: "Venue already exists", CODE: "venue.alreadyExists", @@ -144,6 +165,14 @@ export const FUND_NOT_FOUND_ERROR = Object.freeze({ export const INVALID_OTP = "Invalid OTP"; export const IN_PRODUCTION = process.env.NODE_ENV === "production"; + +export const INVALID_TIMEOUT_RANGE = Object.freeze({ + DESC: "Timeout should be in the range of 15 to 60 minutes.", + CODE: "invalid.timeoutRange", + MESSAGE: "invalid.timeoutRange", + PARAM: "timeout", +}); + export const MEMBER_NOT_FOUND_ERROR = Object.freeze({ DESC: "Member not found", CODE: "member.notFound", @@ -442,8 +471,7 @@ export const NO_CHANGE_IN_TAG_NAME = Object.freeze({ }); export const TAG_ALREADY_EXISTS = Object.freeze({ - MESSAGE: - "A tag with the same name and the same parent tag already exists for this organization.", + MESSAGE: "A tag with the same name already exists at this level", CODE: "tag.alreadyExists", PARAM: "tag.alreadyExists", }); @@ -640,6 +668,13 @@ export const EVENT_VOLUNTEER_INVITE_USER_MISTMATCH = Object.freeze({ PARAM: "eventVolunteers", }); +export const EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR = Object.freeze({ + DESC: "Volunteer membership not found", + CODE: "volunteerMembership.notFound", + MESSAGE: "volunteerMembership.notFound", + PARAM: "volunteerMemberships", +}); + export const USER_ALREADY_CHECKED_IN = Object.freeze({ MESSAGE: "The user has already been checked in for this event.", CODE: "user.alreadyCheckedIn", @@ -696,6 +731,39 @@ export const PRELOGIN_IMAGERY_FIELD_EMPTY = Object.freeze({ PARAM: "preLoginImagery.empty", }); +export const CONTENT_TYPE_SHOULD_BE_MULTIPART_FORM_DATA = Object.freeze({ + DESC: "Invalid content type. Expected multipart/form-data", + MESSAGE: "invalid.contentType", + CODE: "invalid.contentType", +}); + +export const INVALID_FILE_FIELD_NAME = Object.freeze({ + DESC: "Invalid file input field name received.", + MESSAGE: "invalid.fieldFileName", + CODE: "invalid.fieldFileName", +}); + +export const FILE_SIZE_EXCEEDED = Object.freeze({ + DESC: "File size exceeds the allowable limit", + MESSAGE: "file.sizeExceeded", + CODE: "file.sizeExceeded", +}); + +export const FILE_NOT_FOUND = Object.freeze({ + DESC: "File not found.", + MESSAGE: "file.notFound", + CODE: "file.notFound", +}); + +export const INVALID_ARGUMENT_RECEIVED = Object.freeze({ + DESC: "Invalid argument received.", + MESSAGE: "invalid.argument", + CODE: "invalid.argument", +}); + +export const MINIMUM_TIMEOUT_MINUTES = 15; +export const MAXIMUM_TIMEOUT_MINUTES = 60; + export const MAXIMUM_FETCH_LIMIT = 100; export const MAXIMUM_IMAGE_SIZE_LIMIT_KB = 20000; @@ -791,3 +859,14 @@ export const DEFAULT_COMMUNITY = { name: "Palisadoes Foundation", description: "An open source application by Palisadoes Foundation volunteers", }; + +export const ALLOWED_IMAGE_TYPES = [ + "image/jpeg", + "image/png", + "image/gif", + "image/webp", +]; +export const ALLOWED_VIDEO_TYPES = ["video/mp4", "video/mpeg"]; + +export const VIDEO_SIZE_LIMIT = 50 * 1024 * 1024; +export const IMAGE_SIZE_LIMIT = 5 * 1024 * 1024; diff --git a/src/middleware/fileUpload.ts b/src/middleware/fileUpload.ts new file mode 100644 index 0000000000..085d73d35f --- /dev/null +++ b/src/middleware/fileUpload.ts @@ -0,0 +1,74 @@ +import type { Request, Response, NextFunction, RequestHandler } from "express"; +import multer from "multer"; + +import { upload } from "../config/multer"; +import { + ALLOWED_IMAGE_TYPES, + CONTENT_TYPE_SHOULD_BE_MULTIPART_FORM_DATA, + FILE_SIZE_EXCEEDED, + IMAGE_SIZE_LIMIT, + INVALID_FILE_FIELD_NAME, + VIDEO_SIZE_LIMIT, +} from "../constants"; +import { requestContext } from "../libraries"; + +/** + * A middleware for handling optional file uploads. + * All data must be sent as multipart/form-data, but the file field is optional. + * + * @param fieldName - The name of the file field in the form + * @returns Express middleware for handling file upload + */ +export const fileUpload = (fieldName: string): RequestHandler => { + return (req: Request, res: Response, next: NextFunction): void => { + // Validate content type is multipart/form-data + const contentType = req.get("content-type"); + if (contentType && !contentType.includes("multipart/form-data")) { + res.status(400).json({ + error: requestContext.translate( + CONTENT_TYPE_SHOULD_BE_MULTIPART_FORM_DATA.MESSAGE, + ), + }); + return; + } + + // Handle file upload + upload.single(fieldName)(req, res, (err) => { + if (err instanceof multer.MulterError) { + if (err.code === "LIMIT_UNEXPECTED_FILE") { + res.status(400).json({ + error: requestContext.translate(INVALID_FILE_FIELD_NAME.MESSAGE), + }); + return; + } + res.status(400).json({ error: err.message }); + return; + } else if (err) { + res.status(500).json({ error: "File upload failed" }); + return; + } + + // If no file uploaded, continue + if (!req.file) { + next(); + return; + } + + // Validate file size if file was uploaded + const isImage = ALLOWED_IMAGE_TYPES.includes(req.file.mimetype); + const sizeLimit = isImage ? IMAGE_SIZE_LIMIT : VIDEO_SIZE_LIMIT; + + if (req.file.size > sizeLimit) { + const typeStr = isImage ? "Image" : "Video"; + const sizeMB = sizeLimit / (1024 * 1024); + res.status(400).json({ + error: requestContext.translate(FILE_SIZE_EXCEEDED.MESSAGE), + description: `${typeStr} size exceeds the limit of ${sizeMB}MB`, + }); + return; + } + + next(); + }); + }; +}; diff --git a/src/middleware/index.ts b/src/middleware/index.ts index 065f1a55bc..e4518e8e42 100644 --- a/src/middleware/index.ts +++ b/src/middleware/index.ts @@ -1,2 +1,3 @@ // Export everything from this module, including isAuth function export * from "./isAuth"; +export * from "./fileUpload"; diff --git a/src/middleware/isAuth.ts b/src/middleware/isAuth.ts index 7e96dcdf39..504abf1cda 100644 --- a/src/middleware/isAuth.ts +++ b/src/middleware/isAuth.ts @@ -1,7 +1,7 @@ -import type { Request } from "express"; +import type { NextFunction, Request, Response } from "express"; import jwt from "jsonwebtoken"; -import { ACCESS_TOKEN_SECRET } from "../constants"; -import { logger } from "../libraries"; +import { ACCESS_TOKEN_SECRET, UNAUTHENTICATED_ERROR } from "../constants"; +import { logger, requestContext } from "../libraries"; // This interface represents the type of data object returned by isAuth function. export interface InterfaceAuthData { @@ -58,7 +58,8 @@ export const isAuth = (request: Request): InterfaceAuthData => { authData.expired = true; return authData; } - } catch (e) { + } catch (err) { + logger.error(err); authData.expired = true; return authData; } @@ -76,3 +77,53 @@ export const isAuth = (request: Request): InterfaceAuthData => { // Return the finalized authData object return authData; }; + +// Extend the Express Request interface locally +export interface InterfaceAuthenticatedRequest extends Request { + isAuth?: boolean; + userId?: string; + tokenExpired?: boolean; +} + +/** + * Middleware for REST APIs to authenticate users based on the JWT token in the Authorization header. + * + * This middleware checks if the incoming request has a valid JWT token. It sets the authentication + * status, user ID, and token expiration status on the `req` object for downstream middleware and + * route handlers to use. + * + * @param req - The incoming request object. The JWT token is expected in the `Authorization` header. + * @param res - The response object. If authentication fails, an HTTP 401 response will be sent. + * @param next - The next middleware function in the stack. It is called if the user is authenticated. + * + * @returns Returns a 401 Unauthorized response if the user is not authenticated or the token has expired. + * + * @example + * ```typescript + * app.use("/api/protected-route", isAuthMiddleware, (req, res) => { + * if (req.isAuth) { + * res.json({ message: "This is a protected route" }); + * } + * }); + * ``` + */ +export const isAuthMiddleware = ( + req: InterfaceAuthenticatedRequest, + res: Response, + next: NextFunction, +): void => { + const authData: InterfaceAuthData = isAuth(req); + req.isAuth = authData.isAuth; + req.userId = authData.userId; + req.tokenExpired = authData.expired; + + if (!authData.isAuth) { + res.status(401).json({ + message: requestContext.translate(UNAUTHENTICATED_ERROR.MESSAGE), + expired: authData.expired, + }); + return; + } + + next(); +}; diff --git a/src/models/ActionItem.ts b/src/models/ActionItem.ts index fe99964a0a..94904a25a7 100644 --- a/src/models/ActionItem.ts +++ b/src/models/ActionItem.ts @@ -5,13 +5,18 @@ import type { InterfaceEvent } from "./Event"; import type { InterfaceActionItemCategory } from "./ActionItemCategory"; import { MILLISECONDS_IN_A_WEEK } from "../constants"; import type { InterfaceOrganization } from "./Organization"; +import type { InterfaceEventVolunteerGroup } from "./EventVolunteerGroup"; +import type { InterfaceEventVolunteer } from "./EventVolunteer"; /** * Interface representing a database document for ActionItem in MongoDB. */ export interface InterfaceActionItem { _id: Types.ObjectId; - assignee: PopulatedDoc; + assignee: PopulatedDoc; + assigneeGroup: PopulatedDoc; + assigneeUser: PopulatedDoc; + assigneeType: "EventVolunteer" | "EventVolunteerGroup" | "User"; assigner: PopulatedDoc; actionItemCategory: PopulatedDoc< InterfaceActionItemCategory & Document @@ -22,7 +27,7 @@ export interface InterfaceActionItem { dueDate: Date; completionDate: Date; isCompleted: boolean; - allotedHours: number | null; + allottedHours: number | null; organization: PopulatedDoc; event: PopulatedDoc; creator: PopulatedDoc; @@ -33,6 +38,9 @@ export interface InterfaceActionItem { /** * Defines the schema for the ActionItem document. * @param assignee - User to whom the ActionItem is assigned. + * @param assigneeGroup - Group to whom the ActionItem is assigned. + * @param assigneeUser - Organization User to whom the ActionItem is assigned. + * @param assigneeType - Type of assignee (User or Group). * @param assigner - User who assigned the ActionItem. * @param actionItemCategory - ActionItemCategory to which the ActionItem belongs. * @param preCompletionNotes - Notes recorded before completion. @@ -41,7 +49,7 @@ export interface InterfaceActionItem { * @param dueDate - Due date for the ActionItem. * @param completionDate - Date when the ActionItem was completed. * @param isCompleted - Flag indicating if the ActionItem is completed. - * @param allotedHours - Optional: Number of hours alloted for the ActionItem. + * @param allottedHours - Optional: Number of hours allotted for the ActionItem. * @param event - Optional: Event to which the ActionItem is related. * @param organization - Organization to which the ActionItem belongs. * @param creator - User who created the ActionItem. @@ -51,9 +59,21 @@ export interface InterfaceActionItem { const actionItemSchema = new Schema( { assignee: { + type: Schema.Types.ObjectId, + ref: "EventVolunteer", + }, + assigneeGroup: { + type: Schema.Types.ObjectId, + ref: "EventVolunteerGroup", + }, + assigneeUser: { type: Schema.Types.ObjectId, ref: "User", + }, + assigneeType: { + type: String, required: true, + enum: ["EventVolunteer", "EventVolunteerGroup", "User"], }, assigner: { type: Schema.Types.ObjectId, @@ -91,7 +111,7 @@ const actionItemSchema = new Schema( required: true, default: false, }, - allotedHours: { + allottedHours: { type: Number, }, organization: { diff --git a/src/models/DirectChat.ts b/src/models/Chat.ts similarity index 51% rename from src/models/DirectChat.ts rename to src/models/Chat.ts index 3715e0f687..563550d7bb 100644 --- a/src/models/DirectChat.ts +++ b/src/models/Chat.ts @@ -1,34 +1,42 @@ import type { PopulatedDoc, Types, Document, Model } from "mongoose"; import { Schema, model, models } from "mongoose"; -import type { InterfaceDirectChatMessage } from "./DirectChatMessage"; import type { InterfaceOrganization } from "./Organization"; import type { InterfaceUser } from "./User"; import { createLoggingMiddleware } from "../libraries/dbLogger"; +import type { InterfaceChatMessage } from "./ChatMessage"; /** * Interface representing a document for direct chat in MongoDB. */ -export interface InterfaceDirectChat { +export interface InterfaceChat { _id: Types.ObjectId; + isGroup: boolean; + name: string; users: PopulatedDoc[]; - messages: PopulatedDoc[]; + messages: PopulatedDoc[]; creatorId: PopulatedDoc; organization: PopulatedDoc; status: string; + admins: PopulatedDoc[]; createdAt: Date; updatedAt: Date; + lastMessageId: string; } /** - * Mongoose schema for a direct chat. + * Mongoose schema for a chat. + * @param isGroup - Indicates if the chat is a group chat. + * @param name - Name of the chat if its a group chat. * @param users - Users participating in the chat. * @param messages - Messages in the chat. * @param creatorId - Creator of the chat, reference to `User` model. + * @param admins - Admins of the chat if its a group chat, reference to `User` model. * @param organization - Organization associated with the chat, reference to `Organization` model. * @param status - Status of the chat (ACTIVE, BLOCKED, DELETED). * @param createdAt - Timestamp of chat creation. * @param updatedAt - Timestamp of chat update. + * @param lastMessageId - ID of the last message in the chat. */ -const directChatSchema = new Schema( +const chatSchema = new Schema( { users: [ { @@ -37,10 +45,22 @@ const directChatSchema = new Schema( required: true, }, ], + isGroup: { + type: Boolean, + required: true, + }, + name: { + type: String, + required: false, + }, + image: { + type: String, + require: false, + }, messages: [ { type: Schema.Types.ObjectId, - ref: "DirectChatMessage", + ref: "ChatMessage", }, ], creatorId: { @@ -48,28 +68,53 @@ const directChatSchema = new Schema( ref: "User", required: true, }, + admins: [ + { + type: Schema.Types.ObjectId, + ref: "User", + required: false, + }, + ], status: { type: String, required: true, enum: ["ACTIVE", "BLOCKED", "DELETED"], default: "ACTIVE", }, + organization: { + type: Schema.Types.ObjectId, + ref: "Organization", + required: false, + }, + createdAt: { + type: Date, + required: true, + }, + updatedAt: { + type: Date, + required: true, + }, + lastMessageId: { + type: String, + required: false, + }, }, { timestamps: true, }, ); -// Add logging middleware for directChatSchema -createLoggingMiddleware(directChatSchema, "DirectChat"); +// Add logging middleware for Chat +createLoggingMiddleware(chatSchema, "Chat"); /** - * Retrieves or creates the Mongoose model for DirectChat. + * Retrieves or creates the Mongoose model for Chat. * Prevents Mongoose OverwriteModelError during testing. */ -const directChatModel = (): Model => - model("DirectChat", directChatSchema); +const chatModel = (): Model => + model("Chat", chatSchema); // This syntax is needed to prevent Mongoose OverwriteModelError while running tests. -export const DirectChat = (models.DirectChat || - directChatModel()) as ReturnType; +export const Chat = (models.Chat || chatModel()) as ReturnType< + typeof chatModel +>; diff --git a/src/models/ChatMessage.ts b/src/models/ChatMessage.ts new file mode 100644 index 0000000000..1b2d9529a3 --- /dev/null +++ b/src/models/ChatMessage.ts @@ -0,0 +1,109 @@ +import type { PopulatedDoc, Types, Document, Model } from "mongoose"; +import { Schema, model, models } from "mongoose"; +import type { InterfaceUser } from "./User"; +import { createLoggingMiddleware } from "../libraries/dbLogger"; +import type { InterfaceChat } from "./Chat"; + +/** + * Represents a document for a chat message in the MongoDB database. + */ +export interface InterfaceChatMessage { + _id: Types.ObjectId; + chatMessageBelongsTo: PopulatedDoc; + sender: PopulatedDoc; + replyTo: PopulatedDoc; + messageContent: string; + status: string; + deletedBy: PopulatedDoc[]; + createdAt: Date; + updatedAt: Date; +} + +/** + * ChatMessage Schema + * + * This schema defines the structure of a chat message document in the database. + * + * Fields: + * - chatMessageBelongsTo: ObjectId, ref: "Chat", required + * - The chat to which this message belongs. + * - sender: ObjectId, ref: "User", required + * - The user who sent the message. + * - replyTo: ObjectId, ref: "ChatMessage", optional + * - The message to which this message is a reply. + * - messageContent: String, required + * - The content of the message. + * - type: String, required, enum: ["STRING", "VIDEO", "IMAGE", "FILE"] + * - The type of the message content. + * - status: String, required, enum: ["ACTIVE", "BLOCKED", "DELETED"], default: "ACTIVE" + * - The status of the message. + * - deletedBy: Array of ObjectId, ref: "User", optional + * - List of users who have deleted the message. + * - updatedAt: Date, required + * - The date when the message was last updated. + * - createdAt: Date, required + * - The date when the message was created. + * + * Options: + * - timestamps: Automatically adds createdAt and updatedAt fields. + */ +const chatMessageSchema = new Schema( + { + chatMessageBelongsTo: { + type: Schema.Types.ObjectId, + ref: "Chat", + required: true, + }, + sender: { + type: Schema.Types.ObjectId, + ref: "User", + required: true, + }, + replyTo: { + type: Schema.Types.ObjectId, + ref: "ChatMessage", + required: false, + }, + messageContent: { + type: String, + required: true, + }, + status: { + type: String, + required: true, + enum: ["ACTIVE", "BLOCKED", "DELETED"], + default: "ACTIVE", + }, + deletedBy: [ + { + type: Schema.Types.ObjectId, + ref: "User", + required: false, + }, + ], + updatedAt: { + type: Date, + required: true, + }, + createdAt: { + type: Date, + required: true, + }, + }, + { + timestamps: true, // Adds createdAt and updatedAt automatically + }, +); + +// Apply logging middleware to the schema +createLoggingMiddleware(chatMessageSchema, "ChatMessage"); + +/** + * Returns the Mongoose Model for ChatMessage to prevent OverwriteModelError. + */ +const chatMessageModel = (): Model => + model("ChatMessage", chatMessageSchema); + +// This syntax is needed to prevent Mongoose OverwriteModelError while running tests. +export const ChatMessage = (models.ChatMessage || + chatMessageModel()) as ReturnType; diff --git a/src/models/Community.ts b/src/models/Community.ts index 329254aae7..2301ed2e2a 100644 --- a/src/models/Community.ts +++ b/src/models/Community.ts @@ -19,6 +19,7 @@ export interface InterfaceCommunity { slack: string; reddit: string; }; // Object containing various social media URLs for the community. + timeout: number; } /** @@ -35,6 +36,9 @@ export interface InterfaceCommunity { * @param youTube - YouTube URL. * @param slack - Slack URL. * @param reddit - Reddit URL. + * @param websiteLink - Community website URL. + * @param name - Community name. + * @param timeout - Timeout duration in minutes (default is 30 minutes). */ const communitySchema = new Schema({ name: { @@ -73,6 +77,12 @@ const communitySchema = new Schema({ type: String, }, }, + timeout: { + type: Number, + default: 30, + min: [15, "Timeout should be at least 15 minutes."], + max: [60, "Timeout should not exceed 60 minutes."], + }, }); /** diff --git a/src/models/DirectChatMessage.ts b/src/models/DirectChatMessage.ts deleted file mode 100644 index a31dcf809b..0000000000 --- a/src/models/DirectChatMessage.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { PopulatedDoc, Types, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceDirectChat } from "./DirectChat"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; - -/** - * Represents a document for a direct chat message in the MongoDB database. - */ -export interface InterfaceDirectChatMessage { - _id: Types.ObjectId; - directChatMessageBelongsTo: PopulatedDoc; - sender: PopulatedDoc; - receiver: PopulatedDoc; - messageContent: string; - status: string; - createdAt: Date; - updatedAt: Date; -} - -/** - * Mongoose schema definition for a direct chat message document. - * @param directChatMessageBelongsTo - Reference to the direct chat session to which the message belongs. - * @param sender - Reference to the user who sent the message. - * @param receiver - Reference to the user who received the message. - * @param messageContent - Content of the direct chat message. - * @param status - Status of the message (ACTIVE, BLOCKED, DELETED). - * @param createdAt - Date when the direct chat message was created. - * @param updatedAt - Date when the direct chat message was last updated. - */ -const directChatMessageSchema = new Schema( - { - directChatMessageBelongsTo: { - type: Schema.Types.ObjectId, - ref: "DirectChat", - required: true, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - receiver: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - messageContent: { - type: String, - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], - default: "ACTIVE", - }, - }, - { - timestamps: true, // Adds createdAt and updatedAt automatically - }, -); - -// Apply logging middleware to the schema -createLoggingMiddleware(directChatMessageSchema, "DirectChatMessage"); - -/** - * Returns the Mongoose Model for DirectChatMessage to prevent OverwriteModelError. - */ -const directChatMessageModel = (): Model => - model( - "DirectChatMessage", - directChatMessageSchema, - ); - -// This syntax is needed to prevent Mongoose OverwriteModelError while running tests. -export const DirectChatMessage = (models.DirectChatMessage || - directChatMessageModel()) as ReturnType; diff --git a/src/models/Event.ts b/src/models/Event.ts index 2a30077aad..f853682271 100644 --- a/src/models/Event.ts +++ b/src/models/Event.ts @@ -6,6 +6,7 @@ import { createLoggingMiddleware } from "../libraries/dbLogger"; import type { InterfaceEventVolunteerGroup } from "./EventVolunteerGroup"; import type { InterfaceRecurrenceRule } from "./RecurrenceRule"; import type { InterfaceAgendaItem } from "./AgendaItem"; +import type { InterfaceEventVolunteer } from "./EventVolunteer"; /** * Represents a document for an event in the MongoDB database. @@ -37,6 +38,7 @@ export interface InterfaceEvent { startTime: string | undefined; title: string; updatedAt: Date; + volunteers: PopulatedDoc[]; volunteerGroups: PopulatedDoc[]; agendaItems: PopulatedDoc[]; } @@ -66,6 +68,7 @@ export interface InterfaceEvent { * @param admins - Array of admins for the event. * @param organization - Reference to the organization hosting the event. * @param volunteerGroups - Array of volunteer groups associated with the event. + * @param volunteers - Array of volunteers associated with the event. * @param createdAt - Timestamp of when the event was created. * @param updatedAt - Timestamp of when the event was last updated. */ @@ -178,6 +181,14 @@ const eventSchema = new Schema( ref: "Organization", required: true, }, + volunteers: [ + { + type: Schema.Types.ObjectId, + ref: "EventVolunteer", + required: true, + default: [], + }, + ], volunteerGroups: [ { type: Schema.Types.ObjectId, diff --git a/src/models/EventVolunteer.ts b/src/models/EventVolunteer.ts index 0600f77b4c..72ccc24d62 100644 --- a/src/models/EventVolunteer.ts +++ b/src/models/EventVolunteer.ts @@ -4,6 +4,7 @@ import type { InterfaceUser } from "./User"; import type { InterfaceEvent } from "./Event"; import { createLoggingMiddleware } from "../libraries/dbLogger"; import type { InterfaceEventVolunteerGroup } from "./EventVolunteerGroup"; +import type { InterfaceActionItem } from "./ActionItem"; /** * Represents a document for an event volunteer in the MongoDB database. @@ -11,60 +12,95 @@ import type { InterfaceEventVolunteerGroup } from "./EventVolunteerGroup"; */ export interface InterfaceEventVolunteer { _id: Types.ObjectId; + creator: PopulatedDoc; + event: PopulatedDoc; + groups: PopulatedDoc[]; + user: PopulatedDoc; + hasAccepted: boolean; + isPublic: boolean; + hoursVolunteered: number; + assignments: PopulatedDoc[]; + hoursHistory: { + hours: number; + date: Date; + }[]; createdAt: Date; - creatorId: PopulatedDoc; - eventId: PopulatedDoc; - groupId: PopulatedDoc; - isAssigned: boolean; - isInvited: boolean; - response: string; updatedAt: Date; - userId: PopulatedDoc; } /** * Mongoose schema definition for an event volunteer document. * This schema defines how the data will be stored in the MongoDB database. * - * @param creatorId - Reference to the user who created the event volunteer entry. - * @param eventId - Reference to the event for which the user volunteers. - * @param groupId - Reference to the volunteer group associated with the event. - * @param response - Response status of the volunteer ("YES", "NO", null). - * @param isAssigned - Indicates if the volunteer is assigned to a specific role. - * @param isInvited - Indicates if the volunteer has been invited to participate. - * @param userId - Reference to the user who is volunteering for the event. + * @param creator - Reference to the user who created the event volunteer entry. + * @param event - Reference to the event for which the user volunteers. + * @param groups - Reference to the volunteer groups associated with the event. + * @param user - Reference to the user who is volunteering for the event. + * @param hasAccepted - Indicates if the volunteer has accepted invite. + * @param isPublic - Indicates if the volunteer is public. + * @param hoursVolunteered - Total hours volunteered by the user. + * @param assignments - List of action items assigned to the volunteer. * @param createdAt - Timestamp of when the event volunteer document was created. * @param updatedAt - Timestamp of when the event volunteer document was last updated. */ const eventVolunteerSchema = new Schema( { - creatorId: { + creator: { type: Schema.Types.ObjectId, ref: "User", required: true, }, - eventId: { + event: { type: Schema.Types.ObjectId, ref: "Event", }, - groupId: { + groups: [ + { + type: Schema.Types.ObjectId, + ref: "EventVolunteerGroup", + default: [], + }, + ], + user: { type: Schema.Types.ObjectId, - ref: "EventVolunteerGroup", - }, - response: { - type: String, - enum: ["YES", "NO", null], + ref: "User", + required: true, }, - isAssigned: { + hasAccepted: { type: Boolean, + required: true, + default: false, }, - isInvited: { + isPublic: { type: Boolean, - }, - userId: { - type: Schema.Types.ObjectId, - ref: "User", required: true, + default: true, + }, + hoursVolunteered: { + type: Number, + default: 0, + }, + assignments: [ + { + type: Schema.Types.ObjectId, + ref: "ActionItem", + default: [], + }, + ], + hoursHistory: { + type: [ + { + hours: { + type: Number, + required: true, + }, + date: { + type: Date, + required: true, + }, + }, + ], + default: [], }, }, { @@ -72,6 +108,9 @@ const eventVolunteerSchema = new Schema( }, ); +// Add index on hourHistory.date +eventVolunteerSchema.index({ "hourHistory.date": 1 }); + // Apply logging middleware to the schema createLoggingMiddleware(eventVolunteerSchema, "EventVolunteer"); diff --git a/src/models/EventVolunteerGroup.ts b/src/models/EventVolunteerGroup.ts index 8f8fc5072e..4bd9f5f438 100644 --- a/src/models/EventVolunteerGroup.ts +++ b/src/models/EventVolunteerGroup.ts @@ -4,6 +4,7 @@ import type { InterfaceUser } from "./User"; import type { InterfaceEvent } from "./Event"; import { createLoggingMiddleware } from "../libraries/dbLogger"; import type { InterfaceEventVolunteer } from "./EventVolunteer"; +import type { InterfaceActionItem } from "./ActionItem"; /** * Represents a document for an event volunteer group in the MongoDB database. @@ -11,42 +12,46 @@ import type { InterfaceEventVolunteer } from "./EventVolunteer"; */ export interface InterfaceEventVolunteerGroup { _id: Types.ObjectId; - createdAt: Date; - creatorId: PopulatedDoc; - eventId: PopulatedDoc; - leaderId: PopulatedDoc; + creator: PopulatedDoc; + event: PopulatedDoc; + leader: PopulatedDoc; name: string; - updatedAt: Date; + description?: string; volunteers: PopulatedDoc[]; volunteersRequired?: number; + assignments: PopulatedDoc[]; + createdAt: Date; + updatedAt: Date; } /** * Mongoose schema definition for an event volunteer group document. * This schema defines how the data will be stored in the MongoDB database. * - * @param creatorId - Reference to the user who created the event volunteer group entry. - * @param eventId - Reference to the event for which the volunteer group is created. - * @param leaderId - Reference to the leader of the volunteer group. + * @param creator - Reference to the user who created the event volunteer group entry. + * @param event - Reference to the event for which the volunteer group is created. + * @param leader - Reference to the leader of the volunteer group. * @param name - Name of the volunteer group. + * @param description - Description of the volunteer group (optional). * @param volunteers - List of volunteers in the group. * @param volunteersRequired - Number of volunteers required for the group (optional). + * @param assignments - List of action items assigned to the volunteer group. * @param createdAt - Timestamp of when the event volunteer group document was created. * @param updatedAt - Timestamp of when the event volunteer group document was last updated. */ const eventVolunteerGroupSchema = new Schema( { - creatorId: { + creator: { type: Schema.Types.ObjectId, ref: "User", required: true, }, - eventId: { + event: { type: Schema.Types.ObjectId, ref: "Event", required: true, }, - leaderId: { + leader: { type: Schema.Types.ObjectId, ref: "User", required: true, @@ -55,6 +60,9 @@ const eventVolunteerGroupSchema = new Schema( type: String, required: true, }, + description: { + type: String, + }, volunteers: [ { type: Schema.Types.ObjectId, @@ -65,6 +73,13 @@ const eventVolunteerGroupSchema = new Schema( volunteersRequired: { type: Number, }, + assignments: [ + { + type: Schema.Types.ObjectId, + ref: "ActionItem", + default: [], + }, + ], }, { timestamps: true, // Automatically manage `createdAt` and `updatedAt` fields diff --git a/src/models/File.ts b/src/models/File.ts index bd8550f2dc..a7336ce08d 100644 --- a/src/models/File.ts +++ b/src/models/File.ts @@ -1,52 +1,119 @@ -import type { Types, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; +// Import third-party modules import { v4 as uuidv4 } from "uuid"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; -/** - * This is an interface representing a document for a file in the database(MongoDB). - */ +import { Schema, model, models } from "mongoose"; +import type { Types, Model } from "mongoose"; + +// Interface definition for a file document export interface InterfaceFile { _id: Types.ObjectId; - name: string; - url: string | undefined; - size: number | undefined; - secret: string; - contentType: string | undefined; - status: string; + fileName: string; + mimeType: string; + size: number; + hash: { + value: string; + algorithm: string; + }; + uri: string; + referenceCount: number; + metadata: Record; // eslint-disable-line @typescript-eslint/no-explicit-any + encryption: boolean; + archived: boolean; + visibility: "PRIVATE" | "PUBLIC"; + backupStatus: string; + status: "ACTIVE" | "BLOCKED" | "DELETED"; createdAt: Date; updatedAt: Date; + archivedAt?: Date; } /** - * Mongoose schema for a file. - * Defines the structure of the file document stored in MongoDB. - * @param name - The name of the file. - * @param url - The URL where the file is stored. + * Mongoose schema for the `File` collection. + * + * This schema defines the structure for storing files in the database, including details such as + * the file name, size, hash, URI, visibility, and status. It also includes metadata, encryption, and archival details. + * The schema automatically manages `createdAt` and `updatedAt` timestamps using Mongoose's `timestamps` option. + * + * @param fileName - The name of the file (defaults to a UUID if not provided). + * @param mimeType - The MIME type of the file (e.g., `image/png`). * @param size - The size of the file in bytes. - * @param secret - A secret key associated with the file. - * @param contentType - The MIME type of the file. - * @param status - The status of the file (e.g., ACTIVE, BLOCKED, DELETED). - * @param createdAt - The date and time when the file was created. - * @param updatedAt - The date and time when the file was last updated. + * @param hash - An object containing the hash value and the algorithm used for the hash. + * @param uri - The URI of the file location. + * @param referenceCount - The number of references to the file (defaults to 1). + * @param metadata - An object containing additional metadata for the file. + * @param encryption - Indicates whether the file is encrypted. + * @param archived - Indicates whether the file is archived. + * @param visibility - File visibility (`PRIVATE` or `PUBLIC`). + * @param backupStatus - The status of the file's backup. + * @param status - The current status of the file (`ACTIVE`, `BLOCKED`, or `DELETED`). + * @param createdAt - The timestamp when the file was created. + * @param updatedAt - The timestamp when the file was last updated. + * @param archivedAt - The timestamp when the file was archived (if applicable). + * + * @example + * ```typescript + * const newFile = new File({ + * fileName: "example.png", + * mimeType: "image/png", + * size: 2048, + * hash: { value: "abc123", algorithm: "sha256" }, + * uri: "/path/to/file", + * }); + * await newFile.save(); + * ``` */ -const fileSchema = new Schema( +const fileSchema = new Schema( { - name: { + fileName: { type: String, required: true, - default: uuidv4(), // Generates a unique identifier for the name by default + default: uuidv4(), }, - url: { + mimeType: { type: String, + required: true, }, size: { type: Number, + required: true, }, - secret: { + hash: { + value: { + type: String, + required: true, + }, + algorithm: { + type: String, + required: true, + }, + }, + uri: { type: String, required: true, }, - contentType: { + referenceCount: { + type: Number, + default: 1, + }, + metadata: { + type: Schema.Types.Mixed, + }, + archivedAt: { + type: Date, + }, + encryption: { + type: Boolean, + default: false, + }, + archived: { + type: Boolean, + default: false, + }, + visibility: { + type: String, + enum: ["PRIVATE", "PUBLIC"], + default: "PUBLIC", + }, + backupStatus: { type: String, }, status: { @@ -57,26 +124,27 @@ const fileSchema = new Schema( }, }, { - timestamps: true, // Automatically adds `createdAt` and `updatedAt` fields + timestamps: true, }, ); -// Add logging middleware for fileSchema -createLoggingMiddleware(fileSchema, "File"); - /** - * Function to retrieve or create the Mongoose model for the File. - * This is necessary to avoid the OverwriteModelError during testing. - * @returns The Mongoose model for the File. + * Creates and exports the Mongoose `File` model. + * + * The `File` model interacts with the `File` collection in the MongoDB database. + * It allows you to create, retrieve, update, and delete file documents based on the defined schema. + * + * @returns The Mongoose model for the `File` collection. + * + * @example + * ```typescript + * const file = await File.findById(fileId); + * console.log(file); + * ``` */ const fileModel = (): Model => model("File", fileSchema); -/** - * The Mongoose model for the File. - * If the model already exists (e.g., during testing), it uses the existing model. - * Otherwise, it creates a new model. - */ export const File = (models.File || fileModel()) as ReturnType< typeof fileModel >; diff --git a/src/models/GroupChat.ts b/src/models/GroupChat.ts deleted file mode 100644 index 3ecf20f70d..0000000000 --- a/src/models/GroupChat.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { Types, PopulatedDoc, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceGroupChatMessage } from "./GroupChatMessage"; -import type { InterfaceOrganization } from "./Organization"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; - -/** - * Interface representing a document for a group chat in the database (MongoDB). - */ -export interface InterfaceGroupChat { - _id: Types.ObjectId; - title: string; - users: PopulatedDoc[]; - messages: PopulatedDoc[]; - creatorId: PopulatedDoc; - createdAt: Date; - updatedAt: Date; - organization: PopulatedDoc; - status: string; -} -/** - * Mongoose schema definition for a group chat document. - * Defines how group chat data will be stored in MongoDB. - * - * @param title - Title of the group chat. - * @param users - Users participating in the group chat. - * @param messages - Messages sent in the group chat. - * @param creatorId - Creator of the group chat. - * @param createdAt - Timestamp of creation - * @param updatedAt - Timestamp of updation - * @param organization - Organization associated with the group chat. - * @param status - Status of the group chat. - */ -const groupChatSchema = new Schema( - { - title: { - type: String, - required: true, - }, - users: [ - { - type: Schema.Types.ObjectId, - ref: "User", - required: true, // At least one user is required - }, - ], - messages: [ - { - type: Schema.Types.ObjectId, - ref: "GroupChatMessage", - }, - ], - creatorId: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - organization: { - type: Schema.Types.ObjectId, - ref: "Organization", - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], // Status must be one of these values - default: "ACTIVE", - }, - }, - { - timestamps: true, // Automatically manage `createdAt` and `updatedAt` fields - }, -); - -/** - * Adds logging middleware to the group chat schema. - * Middleware logs changes to group chat documents. - */ -createLoggingMiddleware(groupChatSchema, "GroupChat"); - -/** - * Creates a Mongoose model for the group chat schema. - * Ensures that we don't create multiple models during testing, which can cause errors. - * - * @returns The GroupChat model. - */ -const groupChatModel = (): Model => - model("GroupChat", groupChatSchema); - -/** - * Export the GroupChat model. - * This syntax ensures we don't get an OverwriteModelError while running tests. - */ -export const GroupChat = (models.GroupChat || groupChatModel()) as ReturnType< - typeof groupChatModel ->; diff --git a/src/models/GroupChatMessage.ts b/src/models/GroupChatMessage.ts deleted file mode 100644 index f3b583bb2b..0000000000 --- a/src/models/GroupChatMessage.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { Types, PopulatedDoc, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceGroupChat } from "./GroupChat"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; - -/** - * Interface representing a document for a group chat message in the database (MongoDB). - */ -export interface InterfaceGroupChatMessage { - _id: Types.ObjectId; - groupChatMessageBelongsTo: PopulatedDoc; - sender: PopulatedDoc; - createdAt: Date; - updatedAt: Date; - messageContent: string; - status: string; -} - -/** - * Mongoose schema for a group chat message. - * Defines the structure of the group chat message document stored in MongoDB. - * @param groupChatMessageBelongsTo - The association referring to the GroupChat model. - * @param sender - The sender of the message. - * @param messageContent - The content of the message. - * @param status - The status of the message (e.g., ACTIVE, BLOCKED, DELETED). - * @param createdAt - The date and time when the message was created. - * @param updatedAt - The date and time when the message was last updated. - */ -const groupChatMessageSchema = new Schema( - { - groupChatMessageBelongsTo: { - type: Schema.Types.ObjectId, - ref: "GroupChat", - required: true, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - messageContent: { - type: String, - required: true, - }, - status: { - type: String, - required: true, - enum: ["ACTIVE", "BLOCKED", "DELETED"], - default: "ACTIVE", - }, - }, - { - timestamps: true, // Automatically adds `createdAt` and `updatedAt` fields - }, -); - -// Add logging middleware for groupChatMessageSchema -createLoggingMiddleware(groupChatMessageSchema, "GroupChatMessage"); - -/** - * Function to retrieve or create the Mongoose model for the GroupChatMessage. - * This is necessary to avoid the OverwriteModelError during testing. - * @returns The Mongoose model for the GroupChatMessage. - */ -const groupChatMessageModel = (): Model => - model("GroupChatMessage", groupChatMessageSchema); - -/** - * The Mongoose model for the GroupChatMessage. - * If the model already exists (e.g., during testing), it uses the existing model. - * Otherwise, it creates a new model. - */ -export const GroupChatMessage = (models.GroupChatMessage || - groupChatMessageModel()) as ReturnType; diff --git a/src/models/MessageChat.ts b/src/models/MessageChat.ts deleted file mode 100644 index 7510ea8d1a..0000000000 --- a/src/models/MessageChat.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { PopulatedDoc, Types, Document, Model } from "mongoose"; -import { Schema, model, models } from "mongoose"; -import type { InterfaceUser } from "./User"; -import { createLoggingMiddleware } from "../libraries/dbLogger"; -/** - * Interface representing a document for a chat in the database (MongoDB). - */ -export interface InterfaceMessageChat { - _id: Types.ObjectId; - message: string; - languageBarrier: boolean; - sender: PopulatedDoc; - receiver: PopulatedDoc; - createdAt: Date; - updatedAt: Date; -} -/** - * Mongoose schema for a Message Chat. - * Defines the structure of the Message Chat document stored in MongoDB. - * @param message - The content of the chat message. - * @param languageBarrier - Indicates if there's a language barrier in the chat. - * @param sender - Reference to the User who sent the chat message. - * @param receiver - Reference to the User who received the chat message. - * @param createdAt - The date and time when the chat was created. - * @param updatedAt - The date and time when the chat was last updated. - */ -const messageChatSchema = new Schema( - { - message: { - type: String, - required: true, - }, - languageBarrier: { - type: Boolean, - required: false, - default: false, - }, - sender: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - receiver: { - type: Schema.Types.ObjectId, - ref: "User", - required: true, - }, - }, - { - timestamps: true, // Automatically adds `createdAt` and `updatedAt` fields - }, -); - -// Add logging middleware for messageChatSchema -createLoggingMiddleware(messageChatSchema, "MessageChat"); - -/** - * Function to retrieve or create the Mongoose model for the MessageChat. - * This is necessary to avoid the OverwriteModelError during testing. - * @returns The Mongoose model for the MessageChat. - */ -const messageChatModel = (): Model => - model("MessageChat", messageChatSchema); - -/** - * The Mongoose model for the MessageChat. - * If the model already exists (e.g., during testing), it uses the existing model. - * Otherwise, it creates a new model. - */ -export const MessageChat = (models.MessageChat || - messageChatModel()) as ReturnType; diff --git a/src/models/OrganizationTagUser.ts b/src/models/OrganizationTagUser.ts index 467a500df5..62228951e5 100644 --- a/src/models/OrganizationTagUser.ts +++ b/src/models/OrganizationTagUser.ts @@ -45,10 +45,22 @@ const organizationTagUserSchema = new Schema({ }, }); -// Index to ensure unique combination of organizationId, parentOrganizationTagUserId, and name +// Define partial indexes to enforce the unique constraints +// two tags at the same level can't have the same name organizationTagUserSchema.index( - { organizationId: 1, parentOrganizationTagUserId: 1, name: 1 }, - { unique: true }, + { organizationId: 1, name: 1 }, + { + unique: true, + partialFilterExpression: { parentTagId: { $eq: null } }, + }, +); + +organizationTagUserSchema.index( + { organizationId: 1, parentTagId: 1, name: 1 }, + { + unique: true, + partialFilterExpression: { parentTagId: { $ne: null } }, + }, ); // Add logging middleware for organizationTagUserSchema diff --git a/src/models/Post.ts b/src/models/Post.ts index f3bd86a624..209db8ba62 100644 --- a/src/models/Post.ts +++ b/src/models/Post.ts @@ -3,6 +3,7 @@ import { Schema, model, models } from "mongoose"; import mongoosePaginate from "mongoose-paginate-v2"; import type { InterfaceOrganization } from "./Organization"; import type { InterfaceUser } from "./User"; +import type { InterfaceFile } from "./File"; import { createLoggingMiddleware } from "../libraries/dbLogger"; /** @@ -13,7 +14,7 @@ export interface InterfacePost { commentCount: number; createdAt: Date; creatorId: PopulatedDoc; - imageUrl: string | undefined | null; + file: PopulatedDoc | null; likeCount: number; likedBy: PopulatedDoc[]; organization: PopulatedDoc; @@ -22,7 +23,6 @@ export interface InterfacePost { text: string; title: string | undefined; updatedAt: Date; - videoUrl: string | undefined | null; } /** @@ -54,13 +54,9 @@ const postSchema = new Schema( enum: ["ACTIVE", "BLOCKED", "DELETED"], default: "ACTIVE", }, - imageUrl: { - type: String, - required: false, - }, - videoUrl: { - type: String, - required: false, + file: { + type: Schema.Types.ObjectId, + ref: "File", }, creatorId: { type: Schema.Types.ObjectId, diff --git a/src/models/TagUser.ts b/src/models/TagUser.ts index cd2ccb8d0c..fd7889ca35 100644 --- a/src/models/TagUser.ts +++ b/src/models/TagUser.ts @@ -30,6 +30,11 @@ const tagUserSchema = new Schema({ ref: "OrganizationTagUser", required: true, }, + organizationId: { + type: Schema.Types.ObjectId, + ref: "Organization", + required: true, + }, tagColor: { type: String, required: false, diff --git a/src/models/User.ts b/src/models/User.ts index 3908629a92..990e131a63 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -48,6 +48,7 @@ export interface InterfaceUser { mobile: string; work: string; }; + eventsAttended: PopulatedDoc[]; registeredEvents: PopulatedDoc[]; status: string; @@ -77,6 +78,7 @@ export interface InterfaceUser { * @param phone - User's contact numbers (home, mobile, work). * @param registeredEvents - Events the user has registered for. * @param status - User's status (ACTIVE, BLOCKED, DELETED). + * @param eventsAttended - Events the user has attended. * @param updatedAt - Timestamp of when the user was last updated. */ const userSchema = new Schema( @@ -220,6 +222,12 @@ const userSchema = new Schema( ref: "Event", }, ], + eventsAttended: [ + { + type: Schema.Types.ObjectId, + ref: "Event", + }, + ], status: { type: String, required: true, diff --git a/src/models/VolunteerMembership.ts b/src/models/VolunteerMembership.ts new file mode 100644 index 0000000000..3342129d10 --- /dev/null +++ b/src/models/VolunteerMembership.ts @@ -0,0 +1,94 @@ +import type { PopulatedDoc, Document, Model, Types } from "mongoose"; +import { Schema, model, models } from "mongoose"; +import type { InterfaceEvent } from "./Event"; +import type { InterfaceEventVolunteer } from "./EventVolunteer"; +import type { InterfaceEventVolunteerGroup } from "./EventVolunteerGroup"; +import { createLoggingMiddleware } from "../libraries/dbLogger"; +import type { InterfaceUser } from "./User"; + +/** + * Represents a document for a volunteer membership in the MongoDB database. + * This interface defines the structure and types of data that a volunteer membership document will hold. + */ +export interface InterfaceVolunteerMembership { + _id: Types.ObjectId; + volunteer: PopulatedDoc; + group: PopulatedDoc; + event: PopulatedDoc; + status: "invited" | "requested" | "accepted" | "rejected"; + createdBy: PopulatedDoc; + updatedBy: PopulatedDoc; + createdAt: Date; + updatedAt: Date; +} + +/** + * Mongoose schema definition for a volunteer group membership document. + * This schema defines how the data will be stored in the MongoDB database. + * + * @param volunteer - Reference to the event volunteer involved in the group membership. + * @param group - Reference to the event volunteer group. Absence denotes a request for individual volunteer request. + * @param event - Reference to the event that the group is part of. + * @param status - Current status of the membership (invited, requested, accepted, rejected). + * @param createdBy - Reference to the user who created the group membership document. + * @param updatedBy - Reference to the user who last updated the group membership document. + * @param createdAt - Timestamp of when the group membership document was created. + * @param updatedAt - Timestamp of when the group membership document was last updated. + */ +const volunteerMembershipSchema = new Schema( + { + volunteer: { + type: Schema.Types.ObjectId, + ref: "EventVolunteer", + required: true, + }, + group: { + type: Schema.Types.ObjectId, + ref: "EventVolunteerGroup", + }, + event: { + type: Schema.Types.ObjectId, + ref: "Event", + required: true, + }, + status: { + type: String, + enum: ["invited", "requested", "accepted", "rejected"], + required: true, + default: "invited", + }, + createdBy: { + type: Schema.Types.ObjectId, + ref: "User", + }, + updatedBy: { + type: Schema.Types.ObjectId, + ref: "User", + }, + }, + { + timestamps: true, // Automatically manage `createdAt` and `updatedAt` fields + }, +); + +// Enable logging on changes in VolunteerMembership collection +createLoggingMiddleware(volunteerMembershipSchema, "VolunteerMembership"); + +/** + * Creates a Mongoose model for the volunteer group membership schema. + * This function ensures that we don't create multiple models during testing, which can cause errors. + * + * @returns The VolunteerMembership model. + */ +const volunteerMembershipModel = (): Model => + model( + "VolunteerMembership", + volunteerMembershipSchema, + ); + +/** + * Export the VolunteerMembership model. + * This syntax ensures we don't get an OverwriteModelError while running tests. + */ +export const VolunteerMembership = (models.VolunteerMembership || + volunteerMembershipModel()) as ReturnType; diff --git a/src/models/index.ts b/src/models/index.ts index 9ce9aed7e7..2da9481412 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -9,8 +9,6 @@ export * from "./CheckIn"; export * from "./CheckOut"; export * from "./Comment"; export * from "./Community"; -export * from "./DirectChat"; -export * from "./DirectChatMessage"; export * from "./Donation"; export * from "./Event"; export * from "./EventAttendee"; @@ -21,13 +19,10 @@ export * from "./File"; export * from "./Fund"; export * from "./FundraisingCampaign"; export * from "./Group"; -export * from "./GroupChat"; -export * from "./GroupChatMessage"; export * from "./ImageHash"; export * from "./Language"; export * from "./MembershipRequest"; export * from "./Message"; -export * from "./MessageChat"; export * from "./Organization"; export * from "./OrganizationCustomField"; export * from "./OrganizationTagUser"; @@ -38,5 +33,8 @@ export * from "./RecurrenceRule"; export * from "./SampleData"; export * from "./TagUser"; export * from "./Venue"; +export * from "./VolunteerMembership"; export * from "./User"; export * from "./Note"; +export * from "./Chat"; +export * from "./ChatMessage"; diff --git a/src/resolvers/Chat/admins.ts b/src/resolvers/Chat/admins.ts new file mode 100644 index 0000000000..a1028aa4e2 --- /dev/null +++ b/src/resolvers/Chat/admins.ts @@ -0,0 +1,14 @@ +import { User } from "../../models"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This resolver function will fetch and return the list of all chat admins from the database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains the list of users. + */ +export const admins: ChatResolvers["users"] = async (parent) => { + return await User.find({ + _id: { + $in: parent.users, + }, + }).lean(); +}; diff --git a/src/resolvers/DirectChat/creator.ts b/src/resolvers/Chat/creator.ts similarity index 51% rename from src/resolvers/DirectChat/creator.ts rename to src/resolvers/Chat/creator.ts index 02fed5c4a9..8d76e1ec3b 100644 --- a/src/resolvers/DirectChat/creator.ts +++ b/src/resolvers/Chat/creator.ts @@ -1,11 +1,11 @@ import { User } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the specified Direct Chat User from database. + * This resolver function will fetch and return the specified Chat User from database. * @param parent - An object that is the return value of the resolver for this field's parent. * @returns An `object` that contains the User data. */ -export const creator: DirectChatResolvers["creator"] = async (parent) => { +export const creator: ChatResolvers["creator"] = async (parent) => { return await User.findOne({ _id: parent.creatorId, }).lean(); diff --git a/src/resolvers/GroupChat/index.ts b/src/resolvers/Chat/index.ts similarity index 57% rename from src/resolvers/GroupChat/index.ts rename to src/resolvers/Chat/index.ts index 9c81560015..d4559ae213 100644 --- a/src/resolvers/GroupChat/index.ts +++ b/src/resolvers/Chat/index.ts @@ -1,12 +1,14 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; import { creator } from "./creator"; import { messages } from "./messages"; import { organization } from "./organization"; import { users } from "./users"; +import { admins } from "./admins"; -export const GroupChat: GroupChatResolvers = { +export const Chat: ChatResolvers = { creator, messages, organization, users, + admins, }; diff --git a/src/resolvers/Chat/messages.ts b/src/resolvers/Chat/messages.ts new file mode 100644 index 0000000000..db16a74708 --- /dev/null +++ b/src/resolvers/Chat/messages.ts @@ -0,0 +1,14 @@ +import { ChatMessage } from "../../models"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This resolver function will fetch and return the list of all messages in specified Chat from database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains the list of messages. + */ +export const messages: ChatResolvers["messages"] = async (parent) => { + return await ChatMessage.find({ + _id: { + $in: parent.messages, + }, + }).lean(); +}; diff --git a/src/resolvers/DirectChat/organization.ts b/src/resolvers/Chat/organization.ts similarity index 82% rename from src/resolvers/DirectChat/organization.ts rename to src/resolvers/Chat/organization.ts index 9073af15f4..b5692d9392 100644 --- a/src/resolvers/DirectChat/organization.ts +++ b/src/resolvers/Chat/organization.ts @@ -2,15 +2,13 @@ import type { InterfaceOrganization } from "../../models"; import { Organization } from "../../models"; import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the Organization for the Direct Chat from database. + * This resolver function will fetch and return the Organization for the Chat from database. * @param parent - An object that is the return value of the resolver for this field's parent. * @returns An `object` that contains Organization data. */ -export const organization: DirectChatResolvers["organization"] = async ( - parent, -) => { +export const organization: ChatResolvers["organization"] = async (parent) => { const organizationFoundInCache = await findOrganizationsInCache([ parent.organization, ]); diff --git a/src/resolvers/DirectChat/users.ts b/src/resolvers/Chat/users.ts similarity index 65% rename from src/resolvers/DirectChat/users.ts rename to src/resolvers/Chat/users.ts index ebb3893c7f..3912780779 100644 --- a/src/resolvers/DirectChat/users.ts +++ b/src/resolvers/Chat/users.ts @@ -1,11 +1,11 @@ import { User } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; +import type { ChatResolvers } from "../../types/generatedGraphQLTypes"; /** - * This resolver function will fetch and return the list of all direct chat users from the database. + * This resolver function will fetch and return the list of all chat users from the database. * @param parent - An object that is the return value of the resolver for this field's parent. * @returns An `object` that contains the list of users. */ -export const users: DirectChatResolvers["users"] = async (parent) => { +export const users: ChatResolvers["users"] = async (parent) => { return await User.find({ _id: { $in: parent.users, diff --git a/src/resolvers/ChatMessage/chatMessageBelongsTo.ts b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts new file mode 100644 index 0000000000..bdd5277b6b --- /dev/null +++ b/src/resolvers/ChatMessage/chatMessageBelongsTo.ts @@ -0,0 +1,25 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; +import { CHAT_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver method will retrieve and return from the database the Chat to which the specified message belongs. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains the Chat data. + */ +export const chatMessageBelongsTo: ChatMessageResolvers["chatMessageBelongsTo"] = + async (parent) => { + const chatResult = await Chat.findOne({ + _id: parent.chatMessageBelongsTo, + }).lean(); + + if (chatResult) { + return chatResult; + } else { + throw new errors.NotFoundError( + requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), + CHAT_NOT_FOUND_ERROR.CODE, + CHAT_NOT_FOUND_ERROR.PARAM, + ); + } + }; diff --git a/src/resolvers/ChatMessage/index.ts b/src/resolvers/ChatMessage/index.ts new file mode 100644 index 0000000000..3b1d0e60f0 --- /dev/null +++ b/src/resolvers/ChatMessage/index.ts @@ -0,0 +1,10 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { chatMessageBelongsTo } from "./chatMessageBelongsTo"; +import { replyTo } from "./replyTo"; +import { sender } from "./sender"; + +export const ChatMessage: ChatMessageResolvers = { + chatMessageBelongsTo, + sender, + replyTo, +}; diff --git a/src/resolvers/ChatMessage/replyTo.ts b/src/resolvers/ChatMessage/replyTo.ts new file mode 100644 index 0000000000..ff2dc872bb --- /dev/null +++ b/src/resolvers/ChatMessage/replyTo.ts @@ -0,0 +1,28 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { ChatMessage } from "../../models"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver function will fetch and return the message replied to specific to the chat from the database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains reply Message's data. + */ +export const replyTo: ChatMessageResolvers["replyTo"] = async (parent) => { + if (parent.replyTo) { + const result = await ChatMessage.findOne({ + _id: parent.replyTo, + }).lean(); + + if (result) { + return result; + } else { + throw new errors.NotFoundError( + requestContext.translate(MESSAGE_NOT_FOUND_ERROR.MESSAGE), + MESSAGE_NOT_FOUND_ERROR.CODE, + MESSAGE_NOT_FOUND_ERROR.PARAM, + ); + } + } else { + return null; + } +}; diff --git a/src/resolvers/ChatMessage/sender.ts b/src/resolvers/ChatMessage/sender.ts new file mode 100644 index 0000000000..c318fdd7ae --- /dev/null +++ b/src/resolvers/ChatMessage/sender.ts @@ -0,0 +1,24 @@ +import type { ChatMessageResolvers } from "../../types/generatedGraphQLTypes"; +import { User } from "../../models"; +import { USER_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +/** + * This resolver function will fetch and return the sender(user) of the Chat from the database. + * @param parent - An object that is the return value of the resolver for this field's parent. + * @returns An `object` that contains User's data. + */ +export const sender: ChatMessageResolvers["sender"] = async (parent) => { + const result = await User.findOne({ + _id: parent.sender, + }).lean(); + + if (result) { + return result; + } else { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } +}; diff --git a/src/resolvers/DirectChat/index.ts b/src/resolvers/DirectChat/index.ts deleted file mode 100644 index 8a0f6a4059..0000000000 --- a/src/resolvers/DirectChat/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; -import { creator } from "./creator"; -import { messages } from "./messages"; -import { organization } from "./organization"; -import { users } from "./users"; - -/** - * Resolver function for the `DirectChat` type. - * - * This resolver is used to resolve the fields of a `DirectChat` type. - * - * @see users - The resolver function for the `users` field of a `DirectChat`. - * @see organization - The resolver function for the `organization` field of a `DirectChat`. - * @see messages - The resolver function for the `messages` field of a `DirectChat`. - * @see creator - The resolver function for the `creator` field of a `DirectChat`. - * @see DirectChatResolvers - The type definition for the resolvers of the DirectChat fields. - * - */ -export const DirectChat: DirectChatResolvers = { - creator, - messages, - organization, - users, -}; diff --git a/src/resolvers/DirectChat/messages.ts b/src/resolvers/DirectChat/messages.ts deleted file mode 100644 index 3a3332ff88..0000000000 --- a/src/resolvers/DirectChat/messages.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DirectChatMessage } from "../../models"; -import type { DirectChatResolvers } from "../../types/generatedGraphQLTypes"; -/** - * This resolver function will fetch and return the list of all messages in specified Direct Chat from database. - * @param parent - An object that is the return value of the resolver for this field's parent. - * @returns An `object` that contains the list of messages. - */ -export const messages: DirectChatResolvers["messages"] = async (parent) => { - return await DirectChatMessage.find({ - _id: { - $in: parent.messages, - }, - }).lean(); -}; diff --git a/src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts b/src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts deleted file mode 100644 index eb6a0d4d32..0000000000 --- a/src/resolvers/DirectChatMessage/directChatMessageBelongsTo.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { DirectChat } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `directChatMessageBelongsTo` field of a `DirectChatMessage`. - * - * This function retrieves the direct chat to which a specific direct chat message belongs. - * - * @param parent - The parent object representing the direct chat message. It contains information about the direct chat message, including the ID of the direct chat to which it belongs. - * @returns A promise that resolves to the direct chat document found in the database. This document represents the direct chat to which the direct chat message belongs. - * - * @see DirectChat - The DirectChat model used to interact with the direct chats collection in the database. - * @see DirectChatMessageResolvers - The type definition for the resolvers of the DirectChatMessage fields. - * - */ -export const directChatMessageBelongsTo: DirectChatMessageResolvers["directChatMessageBelongsTo"] = - async (parent) => { - const directChatResult = await DirectChat.findOne({ - _id: parent.directChatMessageBelongsTo, - }).lean(); - - if (directChatResult) { - return directChatResult; - } else { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - }; diff --git a/src/resolvers/DirectChatMessage/index.ts b/src/resolvers/DirectChatMessage/index.ts deleted file mode 100644 index e42390c4ec..0000000000 --- a/src/resolvers/DirectChatMessage/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { directChatMessageBelongsTo } from "./directChatMessageBelongsTo"; -import { receiver } from "./receiver"; -import { sender } from "./sender"; - -export const DirectChatMessage: DirectChatMessageResolvers = { - directChatMessageBelongsTo, - receiver, - sender, -}; diff --git a/src/resolvers/DirectChatMessage/receiver.ts b/src/resolvers/DirectChatMessage/receiver.ts deleted file mode 100644 index 1702f33b66..0000000000 --- a/src/resolvers/DirectChatMessage/receiver.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; -import { USER_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `receiver` field of a `DirectChatMessage`. - * - * This function retrieves the user who received a specific direct chat message. - * - * @param parent - The parent object representing the direct chat message. It contains information about the direct chat message, including the ID of the user who received it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who received the direct chat message. - * - * @see User - The User model used to interact with the users collection in the database. - * @see DirectChatMessageResolvers - The type definition for the resolvers of the DirectChatMessage fields. - * - */ -export const receiver: DirectChatMessageResolvers["receiver"] = async ( - parent, -) => { - const result = await User.findOne({ - _id: parent.receiver, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } -}; diff --git a/src/resolvers/DirectChatMessage/sender.ts b/src/resolvers/DirectChatMessage/sender.ts deleted file mode 100644 index 9a20bb4490..0000000000 --- a/src/resolvers/DirectChatMessage/sender.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { DirectChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; -import { USER_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `sender` field of a `DirectChatMessage`. - * - * This function retrieves the user who sent a specific direct chat message. - * - * @param parent - The parent object representing the direct chat message. It contains information about the direct chat message, including the ID of the user who sent it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who sent the direct chat message. - * - * @see User - The User model used to interact with the users collection in the database. - * @see DirectChatMessageResolvers - The type definition for the resolvers of the DirectChatMessage fields. - * - */ -export const sender: DirectChatMessageResolvers["sender"] = async (parent) => { - const result = await User.findOne({ - _id: parent.sender, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } -}; diff --git a/src/resolvers/Event/actionItems.ts b/src/resolvers/Event/actionItems.ts index b40c8a703c..5099572fde 100644 --- a/src/resolvers/Event/actionItems.ts +++ b/src/resolvers/Event/actionItems.ts @@ -15,6 +15,6 @@ import type { EventResolvers } from "../../types/generatedGraphQLTypes"; */ export const actionItems: EventResolvers["actionItems"] = async (parent) => { return await ActionItem.find({ - eventId: parent._id, + event: parent._id, }).lean(); }; diff --git a/src/resolvers/EventVolunteer/creator.ts b/src/resolvers/EventVolunteer/creator.ts deleted file mode 100644 index 59d13f2b57..0000000000 --- a/src/resolvers/EventVolunteer/creator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { User } from "../../models"; -import type { EventVolunteerResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `creator` field of an `EventVolunteer`. - * - * This function retrieves the user who created a specific event volunteer. - * - * @param parent - The parent object representing the event volunteer. It contains information about the event volunteer, including the ID of the user who created it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who created the event volunteer. - * - * @see User - The User model used to interact with the users collection in the database. - * @see EventVolunteerResolvers - The type definition for the resolvers of the EventVolunteer fields. - * - */ -export const creator: EventVolunteerResolvers["creator"] = async (parent) => { - return await User.findOne({ - _id: parent.creatorId, - }).lean(); -}; diff --git a/src/resolvers/EventVolunteer/event.ts b/src/resolvers/EventVolunteer/event.ts deleted file mode 100644 index 438754aa91..0000000000 --- a/src/resolvers/EventVolunteer/event.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Event } from "../../models"; -import type { EventVolunteerResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `event` field of an `EventVolunteer`. - * - * This function retrieves the event associated with a specific event volunteer. - * - * @param parent - The parent object representing the event volunteer. It contains information about the event volunteer, including the ID of the event associated with it. - * @returns A promise that resolves to the event document found in the database. This document represents the event associated with the event volunteer. - * - * @see Event - The Event model used to interact with the events collection in the database. - * @see EventVolunteerResolvers - The type definition for the resolvers of the EventVolunteer fields. - * - */ -export const event: EventVolunteerResolvers["event"] = async (parent) => { - return await Event.findOne({ - _id: parent.eventId, - }).lean(); -}; diff --git a/src/resolvers/EventVolunteer/group.ts b/src/resolvers/EventVolunteer/group.ts deleted file mode 100644 index 4fa94b9ee6..0000000000 --- a/src/resolvers/EventVolunteer/group.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { EventVolunteerGroup } from "../../models"; -import type { EventVolunteerResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `group` field of an `EventVolunteer`. - * - * This function retrieves the group associated with a specific event volunteer. - * - * @param parent - The parent object representing the event volunteer. It contains information about the event volunteer, including the ID of the group associated with it. - * @returns A promise that resolves to the group document found in the database. This document represents the group associated with the event volunteer. - * - * @see EventVolunteerGroup - The EventVolunteerGroup model used to interact with the event volunteer groups collection in the database. - * @see EventVolunteerResolvers - The type definition for the resolvers of the EventVolunteer fields. - * - */ -export const group: EventVolunteerResolvers["group"] = async (parent) => { - return await EventVolunteerGroup.findOne({ - _id: parent.groupId, - }).lean(); -}; diff --git a/src/resolvers/EventVolunteer/index.ts b/src/resolvers/EventVolunteer/index.ts deleted file mode 100644 index 108e57c712..0000000000 --- a/src/resolvers/EventVolunteer/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { EventVolunteerResolvers } from "../../types/generatedGraphQLTypes"; -import { event } from "./event"; -import { creator } from "./creator"; -import { user } from "./user"; -import { group } from "./group"; - -export const EventVolunteer: EventVolunteerResolvers = { - creator, - event, - group, - user, -}; diff --git a/src/resolvers/EventVolunteer/user.ts b/src/resolvers/EventVolunteer/user.ts deleted file mode 100644 index 5059bd1dcb..0000000000 --- a/src/resolvers/EventVolunteer/user.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { User } from "../../models"; -import type { EventVolunteerResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `user` field of an `EventVolunteer`. - * - * This function retrieves the user who created a specific event volunteer. - * - * @param parent - The parent object representing the event volunteer. It contains information about the event volunteer, including the ID of the user who created it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who created the event volunteer. - * - * @see User - The User model used to interact with the users collection in the database. - * @see EventVolunteerResolvers - The type definition for the resolvers of the EventVolunteer fields. - * - */ -export const user: EventVolunteerResolvers["user"] = async (parent) => { - const result = await User.findOne({ - _id: parent.userId, - }).lean(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return result!; -}; diff --git a/src/resolvers/EventVolunteerGroup/creator.ts b/src/resolvers/EventVolunteerGroup/creator.ts deleted file mode 100644 index 7924de2115..0000000000 --- a/src/resolvers/EventVolunteerGroup/creator.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { User } from "../../models"; -import type { EventVolunteerGroupResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `creator` field of an `EventVolunteerGroup`. - * - * This function retrieves the user who created a specific event volunteer group. - * - * @param parent - The parent object representing the event volunteer group. It contains information about the event volunteer group, including the ID of the user who created it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who created the event volunteer group. - * - * @see User - The User model used to interact with the users collection in the database. - * @see EventVolunteerGroupResolvers - The type definition for the resolvers of the EventVolunteerGroup fields. - * - */ -export const creator: EventVolunteerGroupResolvers["creator"] = async ( - parent, -) => { - return await User.findOne({ - _id: parent.creatorId, - }).lean(); -}; diff --git a/src/resolvers/EventVolunteerGroup/event.ts b/src/resolvers/EventVolunteerGroup/event.ts deleted file mode 100644 index b758191d0a..0000000000 --- a/src/resolvers/EventVolunteerGroup/event.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Event } from "../../models"; -import type { EventVolunteerGroupResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `event` field of an `EventVolunteerGroup`. - * - * This function retrieves the event associated with a specific event volunteer group. - * - * @param parent - The parent object representing the event volunteer group. It contains information about the event volunteer group, including the ID of the event associated with it. - * @returns A promise that resolves to the event document found in the database. This document represents the event associated with the event volunteer group. - * - * @see Event - The Event model used to interact with the events collection in the database. - * @see EventVolunteerGroupResolvers - The type definition for the resolvers of the EventVolunteerGroup fields. - * - */ -export const event: EventVolunteerGroupResolvers["event"] = async (parent) => { - return await Event.findOne({ - _id: parent.eventId, - }).lean(); -}; diff --git a/src/resolvers/EventVolunteerGroup/index.ts b/src/resolvers/EventVolunteerGroup/index.ts deleted file mode 100644 index 9c34f29560..0000000000 --- a/src/resolvers/EventVolunteerGroup/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { EventVolunteerGroupResolvers } from "../../types/generatedGraphQLTypes"; -import { leader } from "./leader"; -import { creator } from "./creator"; -import { event } from "./event"; - -export const EventVolunteerGroup: EventVolunteerGroupResolvers = { - creator, - leader, - event, -}; diff --git a/src/resolvers/EventVolunteerGroup/leader.ts b/src/resolvers/EventVolunteerGroup/leader.ts deleted file mode 100644 index 93a47b3eab..0000000000 --- a/src/resolvers/EventVolunteerGroup/leader.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { User } from "../../models"; -import type { InterfaceUser } from "../../models"; -import type { EventVolunteerGroupResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Resolver function for the `leader` field of an `EventVolunteerGroup`. - * - * This function retrieves the user who is the leader of a specific event volunteer group. - * - * @param parent - The parent object representing the event volunteer group. It contains information about the event volunteer group, including the ID of the user who is the leader. - * @returns A promise that resolves to the user document found in the database. This document represents the user who is the leader of the event volunteer group. - * - * @see User - The User model used to interact with the users collection in the database. - * @see EventVolunteerGroupResolvers - The type definition for the resolvers of the EventVolunteerGroup fields. - * - */ -export const leader: EventVolunteerGroupResolvers["leader"] = async ( - parent, -) => { - const groupLeader = await User.findOne({ - _id: parent.leaderId, - }).lean(); - return groupLeader as InterfaceUser; -}; diff --git a/src/resolvers/GroupChat/creator.ts b/src/resolvers/GroupChat/creator.ts deleted file mode 100644 index ff7ea2cd51..0000000000 --- a/src/resolvers/GroupChat/creator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; - -/** - * Resolver function for the `creator` field of a `GroupChat`. - * - * This function retrieves the user who created a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the ID of the user who created it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who created the group chat. - * - * @see User - The User model used to interact with the users collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const creator: GroupChatResolvers["creator"] = async (parent) => { - return await User.findOne({ - _id: parent.creatorId, - }).lean(); -}; diff --git a/src/resolvers/GroupChat/messages.ts b/src/resolvers/GroupChat/messages.ts deleted file mode 100644 index cb03954b94..0000000000 --- a/src/resolvers/GroupChat/messages.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChatMessage } from "../../models"; - -/** - * Resolver function for the `messages` field of a `GroupChat`. - * - * This function retrieves the messages associated with a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the IDs of the messages associated with it. - * @returns A promise that resolves to the message documents found in the database. These documents represent the messages associated with the group chat. - * - * @see GroupChatMessage - The GroupChatMessage model used to interact with the group chat messages collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const messages: GroupChatResolvers["messages"] = async (parent) => { - return await GroupChatMessage.find({ - _id: { - $in: parent.messages, - }, - }).lean(); -}; diff --git a/src/resolvers/GroupChat/organization.ts b/src/resolvers/GroupChat/organization.ts deleted file mode 100644 index ab83f0f3b3..0000000000 --- a/src/resolvers/GroupChat/organization.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { Organization } from "../../models"; -import type { InterfaceOrganization } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; - -/** - * Resolver function for the `organization` field of a `GroupChat`. - * - * This function retrieves the organization associated with a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the ID of the organization it is associated with. - * @returns A promise that resolves to the organization document found in the database. This document represents the organization associated with the group chat. - * - * @see Organization - The Organization model used to interact with the organizations collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const organization: GroupChatResolvers["organization"] = async ( - parent, -) => { - const organizationFoundInCache = await findOrganizationsInCache([ - parent.organization, - ]); - - if (!organizationFoundInCache.includes(null)) { - return organizationFoundInCache[0] as InterfaceOrganization; - } - - const organization = await Organization.findOne({ - _id: parent.organization, - }).lean(); - if (organization) await cacheOrganizations([organization]); - - return organization as InterfaceOrganization; -}; diff --git a/src/resolvers/GroupChat/users.ts b/src/resolvers/GroupChat/users.ts deleted file mode 100644 index b4e0f363e1..0000000000 --- a/src/resolvers/GroupChat/users.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { GroupChatResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; - -/** - * Resolver function for the `users` field of a `GroupChat`. - * - * This function retrieves the users who are members of a specific group chat. - * - * @param parent - The parent object representing the group chat. It contains information about the group chat, including the IDs of the users who are members of it. - * @returns A promise that resolves to the user documents found in the database. These documents represent the users who are members of the group chat. - * - * @see User - The User model used to interact with the users collection in the database. - * @see GroupChatResolvers - The type definition for the resolvers of the GroupChat fields. - * - */ -export const users: GroupChatResolvers["users"] = async (parent) => { - return await User.find({ - _id: { - $in: parent.users, - }, - }).lean(); -}; diff --git a/src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts b/src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts deleted file mode 100644 index c9e2ec6a08..0000000000 --- a/src/resolvers/GroupChatMessage/groupChatMessageBelongsTo.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChat } from "../../models"; -import { errors, requestContext } from "../../libraries"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * Resolver function for the `groupChatMessageBelongsTo` field of a `GroupChatMessage`. - * - * This function retrieves the group chat to which a specific group chat message belongs. - * - * @param parent - The parent object representing the group chat message. It contains information about the group chat message, including the ID of the group chat to which it belongs. - * @returns A promise that resolves to the group chat document found in the database. This document represents the group chat to which the group chat message belongs. - * - * @see GroupChat - The GroupChat model used to interact with the group chats collection in the database. - * @see GroupChatMessageResolvers - The type definition for the resolvers of the GroupChatMessage fields. - * - */ -export const groupChatMessageBelongsTo: GroupChatMessageResolvers["groupChatMessageBelongsTo"] = - async (parent) => { - const result = await GroupChat.findOne({ - _id: parent.groupChatMessageBelongsTo, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - }; diff --git a/src/resolvers/GroupChatMessage/index.ts b/src/resolvers/GroupChatMessage/index.ts deleted file mode 100644 index b837e04871..0000000000 --- a/src/resolvers/GroupChatMessage/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { groupChatMessageBelongsTo } from "./groupChatMessageBelongsTo"; -import { sender } from "./sender"; - -export const GroupChatMessage: GroupChatMessageResolvers = { - groupChatMessageBelongsTo, - sender, -}; diff --git a/src/resolvers/GroupChatMessage/sender.ts b/src/resolvers/GroupChatMessage/sender.ts deleted file mode 100644 index 9497a05f23..0000000000 --- a/src/resolvers/GroupChatMessage/sender.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { GroupChatMessageResolvers } from "../../types/generatedGraphQLTypes"; -import { User } from "../../models"; -import { USER_NOT_FOUND_ERROR } from "../../constants"; -import { errors, requestContext } from "../../libraries"; - -/** - * Resolver function for the `sender` field of a `GroupChatMessage`. - * - * This function retrieves the user who sent a specific group chat message. - * - * @param parent - The parent object representing the group chat message. It contains information about the group chat message, including the ID of the user who sent it. - * @returns A promise that resolves to the user document found in the database. This document represents the user who sent the group chat message. - * - * @see User - The User model used to interact with the users collection in the database. - * @see GroupChatMessageResolvers - The type definition for the resolvers of the GroupChatMessage fields. - * - */ -export const sender: GroupChatMessageResolvers["sender"] = async (parent) => { - const result = await User.findOne({ - _id: parent.sender, - }).lean(); - - if (result) { - return result; - } else { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } -}; diff --git a/src/resolvers/Mutation/addEventAttendee.ts b/src/resolvers/Mutation/addEventAttendee.ts index 8c4242c484..d683c2047e 100644 --- a/src/resolvers/Mutation/addEventAttendee.ts +++ b/src/resolvers/Mutation/addEventAttendee.ts @@ -172,5 +172,23 @@ export const addEventAttendee: MutationResolvers["addEventAttendee"] = async ( await EventAttendee.create({ ...args.data }); - return requestUser; + const updatedUser = await User.findByIdAndUpdate( + args.data.userId, + { + $push: { + eventsAttended: args.data.eventId, + }, + }, + { new: true }, + ); + + if (updatedUser === null) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + return updatedUser; }; diff --git a/src/resolvers/Mutation/addPeopleToUserTag.ts b/src/resolvers/Mutation/addPeopleToUserTag.ts new file mode 100644 index 0000000000..4be0fd68f1 --- /dev/null +++ b/src/resolvers/Mutation/addPeopleToUserTag.ts @@ -0,0 +1,208 @@ +import { Types } from "mongoose"; +import { + TAG_NOT_FOUND, + USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import type { InterfaceAppUserProfile, InterfaceUser } from "../../models"; +import { + AppUserProfile, + OrganizationTagUser, + TagUser, + User, +} from "../../models"; +import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; +import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; +import { cacheUsers } from "../../services/UserCache/cacheUser"; +import { findUserInCache } from "../../services/UserCache/findUserInCache"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; + +/** + * This function enables an admin to assign a tag to multiple users. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the current user exists and has a profile. + * 2. If the tag object exists. + * 3. If the current user is an admin for the organization of the tag. + * 4. If each user to be assigned the tag exists and belongs to the tag's organization. + * 5. Assign the tag only to users who do not already have it. + * @returns Array of users to whom the tag was assigned. + */ + +export const addPeopleToUserTag: MutationResolvers["addPeopleToUserTag"] = + async (_parent, args, context) => { + let currentUser: InterfaceUser | null; + const userFoundInCache = await findUserInCache([context.userId]); + currentUser = userFoundInCache[0]; + if (currentUser === null) { + currentUser = await User.findOne({ + _id: context.userId, + }).lean(); + if (currentUser !== null) { + await cacheUsers([currentUser]); + } + } + + // Checks whether the currentUser exists. + if (!currentUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + // Get the tag object + const tag = await OrganizationTagUser.findOne({ + _id: args.input.tagId, + }).lean(); + + if (!tag) { + throw new errors.NotFoundError( + requestContext.translate(TAG_NOT_FOUND.MESSAGE), + TAG_NOT_FOUND.CODE, + TAG_NOT_FOUND.PARAM, + ); + } + + let currentUserAppProfile: InterfaceAppUserProfile | null; + + const appUserProfileFoundInCache = await findAppUserProfileCache([ + currentUser.appUserProfileId.toString(), + ]); + + currentUserAppProfile = appUserProfileFoundInCache[0]; + if (currentUserAppProfile === null) { + currentUserAppProfile = await AppUserProfile.findOne({ + userId: currentUser._id, + }).lean(); + if (currentUserAppProfile !== null) { + await cacheAppUserProfile([currentUserAppProfile]); + } + } + if (!currentUserAppProfile) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Boolean to determine whether user is an admin of the organization of the tag. + const currentUserIsOrganizationAdmin = currentUserAppProfile.adminFor.some( + (orgId) => + orgId && + new Types.ObjectId(orgId.toString()).equals(tag.organizationId), + ); + //check whether current user can assign tag to users or not + if ( + !(currentUserIsOrganizationAdmin || currentUserAppProfile.isSuperAdmin) + ) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Check if the request users exist + const requestUsers = await User.find({ + _id: { $in: args.input.userIds }, + }).lean(); + + const requestUserMap = new Map( + requestUsers.map((user) => [user._id.toString(), user]), + ); + + // Validate each user to be assigned the tag + const validRequestUsers = []; + for (const userId of args.input.userIds) { + const requestUser = requestUserMap.get(userId); + + if (!requestUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + // Check that the user to which the tag is to be assigned is a member of the tag's organization + const requestUserBelongsToTagOrganization = + requestUser.joinedOrganizations.some((orgId) => + orgId.equals(tag.organizationId), + ); + + if (!requestUserBelongsToTagOrganization) { + throw new errors.UnauthorizedError( + requestContext.translate( + USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION.MESSAGE, + ), + USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION.CODE, + USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION.PARAM, + ); + } + + validRequestUsers.push(requestUser); + } + + // Check existing tag assignments + const existingTagAssignments = await TagUser.find({ + userId: { $in: validRequestUsers.map((user) => user._id) }, + tagId: tag._id, + }).lean(); + + const existingAssignmentsMap = existingTagAssignments.map((assign) => + assign.userId.toString(), + ); + + // Filter out users who already have the tag + const newAssignments = validRequestUsers.filter( + (user) => !existingAssignmentsMap.includes(user._id.toString()), + ); + + if (newAssignments.length === 0) { + return tag; // No new assignments to be made + } + + // Assign all the ancestor tags + const allAncestorTags = [tag._id]; + let currentTag = tag; + while (currentTag?.parentTagId) { + const currentParentTag = await OrganizationTagUser.findOne({ + _id: currentTag.parentTagId, + }).lean(); + + if (currentParentTag) { + allAncestorTags.push(currentParentTag?._id); + currentTag = currentParentTag; + } + } + + const tagUserDocs = newAssignments.flatMap((user) => + allAncestorTags.map((tagId) => ({ + updateOne: { + filter: { userId: user._id, tagId }, + update: { + $setOnInsert: { + userId: user._id, + tagId, + organizationId: tag.organizationId, + }, + }, + upsert: true, + setDefaultsOnInsert: true, + }, + })), + ); + + if (tagUserDocs.length > 0) { + await TagUser.bulkWrite(tagUserDocs); + } + + return tag; + }; diff --git a/src/resolvers/Mutation/addUserToGroupChat.ts b/src/resolvers/Mutation/addUserToGroupChat.ts deleted file mode 100644 index d71535f578..0000000000 --- a/src/resolvers/Mutation/addUserToGroupChat.ts +++ /dev/null @@ -1,127 +0,0 @@ -import "dotenv/config"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_ALREADY_MEMBER_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { adminCheck } from "../../utilities"; -import type { InterfaceGroupChat } from "../../models"; - -/** - * Mutation resolver function to add a user to a group chat. - * - * This function performs the following actions: - * 1. Checks if the group chat specified by `args.chatId` exists. - * 2. Checks if the organization associated with the group chat exists. - * 3. Verifies that the current user (identified by `context.userId`) is an admin of the organization. - * 4. Confirms that the user to be added (specified by `args.userId`) exists. - * 5. Ensures that the user is not already a member of the group chat. - * 6. Adds the user to the list of users in the group chat and returns the updated group chat. - * - * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. - * @param args - The arguments for the mutation, including: - * - `chatId`: The ID of the group chat to which the user will be added. - * - `userId`: The ID of the user to be added to the group chat. - * @param context - The context for the mutation, including: - * - `userId`: The ID of the current user making the request. - * - * @returns A promise that resolves to the updated group chat document with the new user added. - * - * @see GroupChat - The GroupChat model used to interact with the group chats collection in the database. - * @see Organization - The Organization model used to interact with the organizations collection in the database. - * @see User - The User model used to interact with the users collection in the database. - * @see MutationResolvers - The type definition for the mutation resolvers. - * @see adminCheck - Utility function to check if the current user is an admin of the organization. - * @see findOrganizationsInCache - Service function to retrieve organizations from cache. - * @see cacheOrganizations - Service function to cache updated organization data. - */ -export const addUserToGroupChat: MutationResolvers["addUserToGroupChat"] = - async (_parent, args, context) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks whether groupChat exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) { - await cacheOrganizations([organization]); - } - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id === context.userId is an admin of organization. - await adminCheck(context.userId, organization); - - const userExists = !!(await User.exists({ - _id: args.userId, - })); - - // Checks whether user with _id === args.userId exists. - if (userExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - const isUserGroupChatMember = groupChat.users.some((user) => - user.equals(args.userId), - ); - - // Checks whether user with _id === args.userId is already a member of groupChat. - if (isUserGroupChatMember === true) { - throw new errors.ConflictError( - requestContext.translate(USER_ALREADY_MEMBER_ERROR.MESSAGE), - USER_ALREADY_MEMBER_ERROR.CODE, - USER_ALREADY_MEMBER_ERROR.PARAM, - ); - } - - // Adds args.userId to users list on groupChat's document and returns the updated groupChat. - return (await GroupChat.findOneAndUpdate( - { - _id: args.chatId, - }, - { - $push: { - users: args.userId, - }, - }, - { - new: true, - }, - ).lean()) as InterfaceGroupChat; - }; diff --git a/src/resolvers/Mutation/adminRemoveGroup.ts b/src/resolvers/Mutation/adminRemoveGroup.ts deleted file mode 100644 index 972f6bca06..0000000000 --- a/src/resolvers/Mutation/adminRemoveGroup.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { AppUserProfile, GroupChat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { adminCheck } from "../../utilities"; - -/** - * Mutation resolver function to remove a group chat. - * - * This function performs the following actions: - * 1. Checks if the group chat specified by `args.groupId` exists. - * 2. Verifies that the organization associated with the group chat exists. - * 3. Ensures that the current user (identified by `context.userId`) exists. - * 4. Checks that the current user is authorized as an admin of the organization. - * 5. Deletes the group chat from the database. - * - * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. - * @param args - The arguments for the mutation, including: - * - `groupId`: The ID of the group chat to be removed. - * @param context - The context for the mutation, including: - * - `userId`: The ID of the current user making the request. - * - * @returns A promise that resolves to the deleted group chat document. - * - * @see GroupChat - The GroupChat model used to interact with the group chats collection in the database. - * @see Organization - The Organization model used to interact with the organizations collection in the database. - * @see User - The User model used to interact with the users collection in the database. - * @see AppUserProfile - The AppUserProfile model used to retrieve the user's profile information. - * @see MutationResolvers - The type definition for the mutation resolvers. - * @see adminCheck - Utility function to check if the current user is an admin of the organization. - * @see findOrganizationsInCache - Service function to retrieve organizations from cache. - * @see cacheOrganizations - Service function to cache updated organization data. - */ -export const adminRemoveGroup: MutationResolvers["adminRemoveGroup"] = async ( - _parent, - args, - context, -) => { - const groupChat = await GroupChat.findOne({ - _id: args.groupId, - }).lean(); - - // Checks whether groupChat exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) { - await cacheOrganizations([organization]); - } - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserExists = !!(await User.exists({ - _id: context.userId, - })); - - // Checks currentUser with _id === context.userId exists. - if (currentUserExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const currentUserAppProfile = await AppUserProfile.findOne({ - userId: context.userId, - }).lean(); - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id === context.userId is an admin of organization. - await adminCheck(context.userId, organization); - - //remove message from organization - // org.overwrite({ - // ...org._doc, - // messages: org._doc.posts.filter((message) => message != args.messageId), - // }); - // await org.save(); - - // //remove post from user - // user.overwrite({ - // ...user._doc, - // messages: user._doc.posts.filter((message) => message != args.messageId), - // }); - // await user.save(); - - // Deletes the groupChat. - await GroupChat.deleteOne({ - _id: groupChat._id, - }); - - // Returns the deleted groupChat. - return groupChat; -}; diff --git a/src/resolvers/Mutation/assignToUserTags.ts b/src/resolvers/Mutation/assignToUserTags.ts new file mode 100644 index 0000000000..0aa6ad0ce0 --- /dev/null +++ b/src/resolvers/Mutation/assignToUserTags.ts @@ -0,0 +1,174 @@ +import { Types } from "mongoose"; +import { + TAG_NOT_FOUND, + USER_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_ERROR, +} from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import type { + InterfaceAppUserProfile, + InterfaceOrganizationTagUser, + InterfaceUser, +} from "../../models"; +import { + AppUserProfile, + OrganizationTagUser, + TagUser, + User, +} from "../../models"; +import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; +import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; +import { cacheUsers } from "../../services/UserCache/cacheUser"; +import { findUserInCache } from "../../services/UserCache/findUserInCache"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; + +/** + * This function enables an admin to assign multiple tags to users with a specified tag. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the current user exists and has a profile. + * 2. If the current user is an admin for the organization of the tags. + * 3. If the currentTagId exists and the selected tags exist. + * 4. Assign the tags to users who have the currentTagId. + * @returns Array of tags that were assigned to users. + */ +export const assignToUserTags: MutationResolvers["assignToUserTags"] = async ( + _parent, + args, + context, +) => { + let currentUser: InterfaceUser | null; + const userFoundInCache = await findUserInCache([context.userId]); + currentUser = userFoundInCache[0]; + if (currentUser === null) { + currentUser = await User.findOne({ + _id: context.userId, + }).lean(); + if (currentUser !== null) { + await cacheUsers([currentUser]); + } + } + + // Checks whether the currentUser exists. + if (!currentUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + let currentUserAppProfile: InterfaceAppUserProfile | null; + + const appUserProfileFoundInCache = await findAppUserProfileCache([ + currentUser.appUserProfileId.toString(), + ]); + + currentUserAppProfile = appUserProfileFoundInCache[0]; + if (currentUserAppProfile === null) { + currentUserAppProfile = await AppUserProfile.findOne({ + userId: currentUser._id, + }).lean(); + if (currentUserAppProfile !== null) { + await cacheAppUserProfile([currentUserAppProfile]); + } + } + + if (!currentUserAppProfile) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Get the current tag object + const currentTag = await OrganizationTagUser.findOne({ + _id: args.input.currentTagId, + }).lean(); + + if (!currentTag) { + throw new errors.NotFoundError( + requestContext.translate(TAG_NOT_FOUND.MESSAGE), + TAG_NOT_FOUND.CODE, + TAG_NOT_FOUND.PARAM, + ); + } + + // Boolean to determine whether user is an admin of the organization of the current tag. + const currentUserIsOrganizationAdmin = currentUserAppProfile.adminFor.some( + (orgId) => orgId?.toString() === currentTag.organizationId.toString(), + ); + + if (!(currentUserIsOrganizationAdmin || currentUserAppProfile.isSuperAdmin)) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Find selected tags & all users tagged with the current tag + const [selectedTags, usersWithCurrentTag] = await Promise.all([ + OrganizationTagUser.find({ + _id: { $in: args.input.selectedTagIds }, + }).lean(), + TagUser.find({ tagId: currentTag._id }).lean(), + ]); + + const userIdsWithCurrentTag = usersWithCurrentTag.map( + (userTag) => userTag.userId, + ); + + // Check if all requested tags were found + if (selectedTags.length !== args.input.selectedTagIds.length) { + throw new errors.NotFoundError( + requestContext.translate(TAG_NOT_FOUND.MESSAGE), + TAG_NOT_FOUND.CODE, + TAG_NOT_FOUND.PARAM, + ); + } + + // Find and assign ancestor tags + const allTagsToAssign = new Set(); + for (const tag of selectedTags) { + let currentTagToProcess: InterfaceOrganizationTagUser | null = tag; + while (currentTagToProcess) { + allTagsToAssign.add(currentTagToProcess._id.toString()); + if (currentTagToProcess.parentTagId) { + const parentTag: InterfaceOrganizationTagUser | null = + await OrganizationTagUser.findOne({ + _id: currentTagToProcess.parentTagId, + }).lean(); + currentTagToProcess = parentTag || null; + } else { + currentTagToProcess = null; + } + } + } + + const tagUserDocs = userIdsWithCurrentTag.flatMap((userId) => + Array.from(allTagsToAssign).map((tagId) => ({ + updateOne: { + filter: { userId, tagId: new Types.ObjectId(tagId) }, + update: { + $setOnInsert: { + userId, + tagId: new Types.ObjectId(tagId), + organizationId: currentTag.organizationId, + }, + }, + upsert: true, + setDefaultsOnInsert: true, + }, + })), + ); + + if (tagUserDocs.length > 0) { + await TagUser.bulkWrite(tagUserDocs); + } + + return currentTag; +}; diff --git a/src/resolvers/Mutation/assignUserTag.ts b/src/resolvers/Mutation/assignUserTag.ts index ee2186642d..d7f076ae8a 100644 --- a/src/resolvers/Mutation/assignUserTag.ts +++ b/src/resolvers/Mutation/assignUserTag.ts @@ -171,7 +171,13 @@ export const assignUserTag: MutationResolvers["assignUserTag"] = async ( const tagUserDocs = allAncestorTags.map((tagId) => ({ updateOne: { filter: { userId: assigneeId, tagId }, - update: { $setOnInsert: { userId: assigneeId, tagId } }, + update: { + $setOnInsert: { + userId: assigneeId, + tagId, + organizationId: tag.organizationId, + }, + }, upsert: true, setDefaultsOnInsert: true, }, diff --git a/src/resolvers/Mutation/createActionItem.ts b/src/resolvers/Mutation/createActionItem.ts index c38357a282..718bf1caba 100644 --- a/src/resolvers/Mutation/createActionItem.ts +++ b/src/resolvers/Mutation/createActionItem.ts @@ -3,31 +3,31 @@ import { ACTION_ITEM_CATEGORY_IS_DISABLED, ACTION_ITEM_CATEGORY_NOT_FOUND_ERROR, EVENT_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, - USER_NOT_MEMBER_FOR_ORGANIZATION, } from "../../constants"; import { errors, requestContext } from "../../libraries"; import type { InterfaceActionItem, - InterfaceAppUserProfile, InterfaceEvent, - InterfaceUser, + InterfaceEventVolunteer, + InterfaceEventVolunteerGroup, } from "../../models"; import { ActionItem, ActionItemCategory, - AppUserProfile, Event, - User, + EventVolunteer, + EventVolunteerGroup, } from "../../models"; -import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; -import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; import { cacheEvents } from "../../services/EventCache/cacheEvents"; import { findEventsInCache } from "../../services/EventCache/findEventInCache"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { + checkAppUserProfileExists, + checkUserExists, +} from "../../utilities/checks"; /** * Creates a new action item and assigns it to a user. @@ -38,18 +38,18 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; * 2. Ensures that the current user has an associated app user profile. * 3. Checks if the assignee exists. * 4. Validates if the action item category exists and is not disabled. - * 5. Confirms that the assignee is a member of the organization associated with the action item category. - * 6. If the action item is related to an event, checks if the event exists and whether the current user is an admin of that event. - * 7. Verifies if the current user is an admin of the organization or a superadmin. + * 5. If the action item is related to an event, checks if the event exists and whether the current user is an admin of that event. + * 6. Verifies if the current user is an admin of the organization or a superadmin. * * @param _parent - The parent object for the mutation (not used in this function). * @param args - The arguments provided with the request, including: * - `data`: An object containing: * - `assigneeId`: The ID of the user to whom the action item is assigned. + * - `assigneeType`: The type of the assignee (EventVolunteer or EventVolunteerGroup). * - `preCompletionNotes`: Notes to be added before the action item is completed. * - `dueDate`: The due date for the action item. * - `eventId` (optional): The ID of the event associated with the action item. - * - `actionItemCategoryId`: The ID of the action item category. + * - `actionItemCategoryId`: The ID of the action item category. * @param context - The context of the entire application, including user information and other context-specific data. * * @returns A promise that resolves to the created action item object. @@ -60,62 +60,41 @@ export const createActionItem: MutationResolvers["createActionItem"] = async ( args, context, ): Promise => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); + const currentUser = await checkUserExists(context.userId); + const currentUserAppProfile = await checkAppUserProfileExists(currentUser); + + const { + assigneeId, + assigneeType, + preCompletionNotes, + allottedHours, + dueDate, + eventId, + } = args.data; + + let assignee: InterfaceEventVolunteer | InterfaceEventVolunteerGroup | null; + if (assigneeType === "EventVolunteer") { + assignee = await EventVolunteer.findById(assigneeId) + .populate("user") + .lean(); + if (!assignee) { + throw new errors.NotFoundError( + requestContext.translate(EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE), + EVENT_VOLUNTEER_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_NOT_FOUND_ERROR.PARAM, + ); } - } - - // Checks whether currentUser with _id === context.userId exists. - if (currentUser === null) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - let currentUserAppProfile: InterfaceAppUserProfile | null; - const appUserProfileFoundInCache = await findAppUserProfileCache([ - currentUser.appUserProfileId?.toString(), - ]); - currentUserAppProfile = appUserProfileFoundInCache[0]; - if (currentUserAppProfile === null) { - currentUserAppProfile = await AppUserProfile.findOne({ - userId: currentUser._id, - }).lean(); - if (currentUserAppProfile !== null) { - await cacheAppUserProfile([currentUserAppProfile]); + } else if (assigneeType === "EventVolunteerGroup") { + assignee = await EventVolunteerGroup.findById(assigneeId).lean(); + if (!assignee) { + throw new errors.NotFoundError( + requestContext.translate(EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE), + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.PARAM, + ); } } - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - const assignee = await User.findOne({ - _id: args.data.assigneeId, - }); - - // Checks whether the assignee exists. - if (assignee === null) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const actionItemCategory = await ActionItemCategory.findOne({ _id: args.actionItemCategoryId, }).lean(); @@ -138,36 +117,17 @@ export const createActionItem: MutationResolvers["createActionItem"] = async ( ); } - let asigneeIsOrganizationMember = false; - asigneeIsOrganizationMember = assignee.joinedOrganizations.some( - (organizationId) => - organizationId === actionItemCategory.organizationId || - new mongoose.Types.ObjectId(organizationId.toString()).equals( - actionItemCategory.organizationId, - ), - ); - - // Checks if the asignee is a member of the organization - if (!asigneeIsOrganizationMember) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE), - USER_NOT_MEMBER_FOR_ORGANIZATION.CODE, - USER_NOT_MEMBER_FOR_ORGANIZATION.PARAM, - ); - } - let currentUserIsEventAdmin = false; - - if (args.data.eventId) { + if (eventId) { let currEvent: InterfaceEvent | null; - const eventFoundInCache = await findEventsInCache([args.data.eventId]); + const eventFoundInCache = await findEventsInCache([eventId]); currEvent = eventFoundInCache[0]; if (eventFoundInCache[0] === null) { currEvent = await Event.findOne({ - _id: args.data.eventId, + _id: eventId, }).lean(); if (currEvent !== null) { @@ -203,6 +163,7 @@ export const createActionItem: MutationResolvers["createActionItem"] = async ( ); // Checks whether the currentUser is authorized for the operation. + /* c8 ignore start */ if ( currentUserIsEventAdmin === false && currentUserIsOrgAdmin === false && @@ -214,19 +175,41 @@ export const createActionItem: MutationResolvers["createActionItem"] = async ( USER_NOT_AUTHORIZED_ERROR.PARAM, ); } + /* c8 ignore stop */ // Creates and returns the new action item. const createActionItem = await ActionItem.create({ - assignee: args.data.assigneeId, + assignee: assigneeType === "EventVolunteer" ? assigneeId : undefined, + assigneeGroup: + assigneeType === "EventVolunteerGroup" ? assigneeId : undefined, + assigneeUser: assigneeType === "User" ? assigneeId : undefined, + assigneeType, assigner: context.userId, actionItemCategory: args.actionItemCategoryId, - preCompletionNotes: args.data.preCompletionNotes, - allotedHours: args.data.allotedHours, - dueDate: args.data.dueDate, - event: args.data.eventId, + preCompletionNotes, + allottedHours, + dueDate, + event: eventId, organization: actionItemCategory.organizationId, creator: context.userId, }); + if (assigneeType === "EventVolunteer") { + await EventVolunteer.findByIdAndUpdate(assigneeId, { + $addToSet: { assignments: createActionItem._id }, + }); + } else if (assigneeType === "EventVolunteerGroup") { + const newGrp = (await EventVolunteerGroup.findByIdAndUpdate( + assigneeId, + { $addToSet: { assignments: createActionItem._id } }, + { new: true }, + ).lean()) as InterfaceEventVolunteerGroup; + + await EventVolunteer.updateMany( + { _id: { $in: newGrp.volunteers } }, + { $addToSet: { assignments: createActionItem._id } }, + ); + } + return createActionItem.toObject(); }; diff --git a/src/resolvers/Mutation/createChat.ts b/src/resolvers/Mutation/createChat.ts new file mode 100644 index 0000000000..650707cb44 --- /dev/null +++ b/src/resolvers/Mutation/createChat.ts @@ -0,0 +1,80 @@ +import { + ORGANIZATION_NOT_FOUND_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import { Chat, Organization, User } from "../../models"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +/** + * This function enables to create a chat. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the user exists + * 2. If the organization exists + * @returns Created chat + */ +export const createChat: MutationResolvers["createChat"] = async ( + _parent, + args, + context, +) => { + let organization; + if (args.data.isGroup && args.data.organizationId) { + organization = await Organization.findOne({ + _id: args.data.organizationId, + }); + + // Checks whether organization with _id === args.data.organizationId exists. + if (!organization) { + throw new errors.NotFoundError( + requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), + ORGANIZATION_NOT_FOUND_ERROR.CODE, + ORGANIZATION_NOT_FOUND_ERROR.PARAM, + ); + } + } + + // const userExists = (await User.exists({ + // _id: { $in: args.data.userIds }, + // })) as unknown as string[]; + + const userExists = await User.find({ + _id: { $in: args.data.userIds }, + }).lean(); + + if (userExists && userExists.length !== args.data.userIds.length) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + const now = new Date(); + + const chatPayload = args.data.isGroup + ? { + isGroup: args.data.isGroup, + creatorId: context.userId, + users: args.data.userIds, + organization: args.data.organizationId, + name: args.data?.name, + admins: [context.userId], + createdAt: now, + updatedAt: now, + image: args.data.image, + } + : { + creatorId: context.userId, + users: args.data.userIds, + isGroup: args.data.isGroup, + createdAt: now, + updatedAt: now, + }; + + const createdChat = await Chat.create(chatPayload); + + return createdChat; +}; diff --git a/src/resolvers/Mutation/createDirectChat.ts b/src/resolvers/Mutation/createDirectChat.ts deleted file mode 100644 index 85d352638a..0000000000 --- a/src/resolvers/Mutation/createDirectChat.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { User, DirectChat } from "../../models"; -import { errors, requestContext } from "../../libraries"; - -import { USER_NOT_FOUND_ERROR } from "../../constants"; - -/** - * Creates a new direct chat and associates it with an organization. - * - * This resolver performs the following steps: - * - * 1. Retrieves the organization based on the provided `organizationId`. - * 2. Checks if the organization exists, either from cache or database. - * 3. Validates that all user IDs provided in `userIds` exist. - * 4. Creates a new direct chat with the specified users and organization. - * - * @param _parent - The parent object, not used in this resolver. - * @param args - The input arguments for the mutation, including: - * - `data`: An object containing: - * - `organizationId`: The ID of the organization to associate with the direct chat. - * - `userIds`: An array of user IDs to be included in the direct chat. - * @param context - The context object containing user information (context.userId). - * - * @returns A promise that resolves to the created direct chat object. - * - * @remarks This function includes caching operations to optimize data retrieval and ensures that all user IDs are valid before creating the direct chat. - */ -export const createDirectChat: MutationResolvers["createDirectChat"] = async ( - _parent, - args, - context, -) => { - // Variable to store list of users to be members of directChat. - const usersInDirectChat = []; - - // Loops over each item in args.data.userIds list. - for await (const userId of args.data.userIds) { - const userExists = !!(await User.exists({ - _id: userId, - })); - - // Checks whether user with _id === userId exists. - if (userExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - usersInDirectChat.push(userId); - } - - // Creates new directChat. - const createdDirectChat = await DirectChat.create({ - creatorId: context.userId, - users: usersInDirectChat, - }); - - // Returns createdDirectChat. - return createdDirectChat.toObject(); -}; diff --git a/src/resolvers/Mutation/createEventVolunteer.ts b/src/resolvers/Mutation/createEventVolunteer.ts index decaa931fc..987c88dfb2 100644 --- a/src/resolvers/Mutation/createEventVolunteer.ts +++ b/src/resolvers/Mutation/createEventVolunteer.ts @@ -1,29 +1,25 @@ import { EVENT_NOT_FOUND_ERROR, - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, EVENT_VOLUNTEER_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, } from "../../constants"; import { errors, requestContext } from "../../libraries"; -import type { InterfaceUser } from "../../models"; -import { Event, EventVolunteerGroup, User } from "../../models"; +import { Event, User, VolunteerMembership } from "../../models"; import { EventVolunteer } from "../../models/EventVolunteer"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { adminCheck } from "../../utilities"; +import { checkUserExists } from "../../utilities/checks"; /** * Creates a new event volunteer entry. * * This function performs the following actions: - * 1. Verifies the existence of the current user. - * 2. Verifies the existence of the volunteer user. - * 3. Verifies the existence of the event. - * 4. Verifies the existence of the volunteer group. - * 5. Ensures that the current user is the leader of the volunteer group. - * 6. Creates a new event volunteer record. - * 7. Adds the newly created volunteer to the group's list of volunteers. + * 1. Validates the existence of the current user. + * 2. Checks if the specified user and event exist. + * 3. Verifies that the current user is an admin of the event. + * 4. Creates a new volunteer entry for the event. + * 5. Creates a volunteer membership record for the new volunteer. + * 6. Returns the created event volunteer record. * * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. * @param args - The arguments for the mutation, including: @@ -38,25 +34,11 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; */ export const createEventVolunteer: MutationResolvers["createEventVolunteer"] = async (_parent, args, context) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - if (!currentUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const volunteerUser = await User.findOne({ _id: args.data?.userId }).lean(); + const { eventId, userId } = args.data; + const currentUser = await checkUserExists(context.userId); + + // Check if the volunteer user exists + const volunteerUser = await User.findById(userId).lean(); if (!volunteerUser) { throw new errors.NotFoundError( requestContext.translate(EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE), @@ -64,7 +46,8 @@ export const createEventVolunteer: MutationResolvers["createEventVolunteer"] = EVENT_VOLUNTEER_NOT_FOUND_ERROR.PARAM, ); } - const event = await Event.findById(args.data.eventId); + // Check if the event exists + const event = await Event.findById(eventId).populate("organization").lean(); if (!event) { throw new errors.NotFoundError( requestContext.translate(EVENT_NOT_FOUND_ERROR.MESSAGE), @@ -72,18 +55,18 @@ export const createEventVolunteer: MutationResolvers["createEventVolunteer"] = EVENT_NOT_FOUND_ERROR.PARAM, ); } - const group = await EventVolunteerGroup.findOne({ - _id: args.data.groupId, - }).lean(); - if (!group) { - throw new errors.NotFoundError( - requestContext.translate(EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE), - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.CODE, - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.PARAM, - ); - } - if (group.leaderId.toString() !== currentUser._id.toString()) { + const userIsEventAdmin = event.admins.some( + (admin) => admin.toString() === currentUser?._id.toString(), + ); + + // Checks creator of the event or admin of the organization + const isAdmin = await adminCheck( + currentUser._id, + event.organization, + false, + ); + if (!isAdmin && !userIsEventAdmin) { throw new errors.UnauthorizedError( requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), USER_NOT_AUTHORIZED_ERROR.CODE, @@ -91,24 +74,21 @@ export const createEventVolunteer: MutationResolvers["createEventVolunteer"] = ); } + // create the volunteer const createdVolunteer = await EventVolunteer.create({ - userId: args.data.userId, - eventId: args.data.eventId, - groupId: args.data.groupId, - isAssigned: false, - isInvited: true, - creatorId: context.userId, + user: userId, + event: eventId, + creator: context.userId, + groups: [], + }); + + // create volunteer membership record + await VolunteerMembership.create({ + volunteer: createdVolunteer._id, + event: eventId, + status: "invited", + createdBy: context.userId, }); - await EventVolunteerGroup.findOneAndUpdate( - { - _id: args.data.groupId, - }, - { - $push: { - volunteers: createdVolunteer._id, - }, - }, - ); return createdVolunteer.toObject(); }; diff --git a/src/resolvers/Mutation/createEventVolunteerGroup.ts b/src/resolvers/Mutation/createEventVolunteerGroup.ts index 060a2dde49..d3c26adbd0 100644 --- a/src/resolvers/Mutation/createEventVolunteerGroup.ts +++ b/src/resolvers/Mutation/createEventVolunteerGroup.ts @@ -1,14 +1,17 @@ import { EVENT_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, } from "../../constants"; import { errors, requestContext } from "../../libraries"; -import type { InterfaceUser } from "../../models"; -import { Event, EventVolunteerGroup, User } from "../../models"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; +import { + Event, + EventVolunteer, + EventVolunteerGroup, + VolunteerMembership, +} from "../../models"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { adminCheck } from "../../utilities"; +import { checkUserExists } from "../../utilities/checks"; /** * Creates a new event volunteer group and associates it with an event. @@ -19,14 +22,19 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; * 2. Checks if the specified event exists. * 3. Verifies that the current user is an admin of the event. * 4. Creates a new volunteer group for the event. - * 5. Updates the event to include the newly created volunteer group. + * 5. Fetches or creates new volunteers for the group. + * 6. Creates volunteer group membership records for the new volunteers. + * 7. Updates the event to include the new volunteer group. * * @param _parent - The parent object, not used in this resolver. * @param args - The input arguments for the mutation, including: * - `data`: An object containing: - * - `eventId`: The ID of the event to associate the volunteer group with. - * - `name`: The name of the volunteer group. - * - `volunteersRequired`: The number of volunteers required for the group. + * - `eventId`: The ID of the event to associate the volunteer group with. + * - `name`: The name of the volunteer group. + * - `description`: A description of the volunteer group. + * - `leaderId`: The ID of the user who will lead the volunteer group. + * - `volunteerIds`: An array of user IDs for the volunteers in the group. + * - `volunteersRequired`: The number of volunteers required for the group. * @param context - The context object containing user information (context.userId). * * @returns A promise that resolves to the created event volunteer group object. @@ -35,25 +43,20 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; */ export const createEventVolunteerGroup: MutationResolvers["createEventVolunteerGroup"] = async (_parent, args, context) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - if (!currentUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const event = await Event.findById(args.data.eventId); + const { + eventId, + name, + description, + leaderId, + volunteerUserIds, + volunteersRequired, + } = args.data; + // Validate the existence of the current user + const currentUser = await checkUserExists(context.userId); + + const event = await Event.findById(args.data.eventId) + .populate("organization") + .lean(); if (!event) { throw new errors.NotFoundError( requestContext.translate(EVENT_NOT_FOUND_ERROR.MESSAGE), @@ -66,7 +69,13 @@ export const createEventVolunteerGroup: MutationResolvers["createEventVolunteerG (admin) => admin.toString() === currentUser?._id.toString(), ); - if (!userIsEventAdmin) { + const isAdmin = await adminCheck( + currentUser._id, + event.organization, + false, + ); + // Checks if user is Event Admin or Admin of the organization + if (!isAdmin && !userIsEventAdmin) { throw new errors.UnauthorizedError( requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), USER_NOT_AUTHORIZED_ERROR.CODE, @@ -74,24 +83,57 @@ export const createEventVolunteerGroup: MutationResolvers["createEventVolunteerG ); } + // Create the new volunteer group const createdVolunteerGroup = await EventVolunteerGroup.create({ - eventId: args.data.eventId, - creatorId: context.userId, - leaderId: context.userId, - name: args.data.name, - volunteersRequired: args.data?.volunteersRequired, + creator: context.userId, + event: eventId, + leader: leaderId, + name, + description, + volunteers: [], + volunteersRequired, }); - await Event.findOneAndUpdate( - { - _id: args.data.eventId, - }, - { - $push: { - volunteerGroups: createdVolunteerGroup._id, - }, - }, + // Fetch Volunteers or Create New Ones if Necessary + const volunteers = await EventVolunteer.find({ + user: { $in: volunteerUserIds }, + event: eventId, + }).lean(); + + const existingVolunteerIds = volunteers.map((vol) => vol.user.toString()); + const newVolunteerUserIds = volunteerUserIds.filter( + (id) => !existingVolunteerIds.includes(id), ); + // Bulk Create New Volunteers if Needed + const newVolunteers = await EventVolunteer.insertMany( + newVolunteerUserIds.map((userId) => ({ + user: userId, + event: eventId, + creator: context.userId, + groups: [], + })), + ); + + const allVolunteerIds = [ + ...volunteers.map((v) => v._id.toString()), + ...newVolunteers.map((v) => v._id.toString()), + ]; + + // Bulk Create VolunteerMembership Records + await VolunteerMembership.insertMany( + allVolunteerIds.map((volunteerId) => ({ + volunteer: volunteerId, + group: createdVolunteerGroup._id, + event: eventId, + status: "invited", + createdBy: context.userId, + })), + ); + + await Event.findByIdAndUpdate(eventId, { + $push: { volunteerGroups: createdVolunteerGroup._id }, + }); + return createdVolunteerGroup.toObject(); }; diff --git a/src/resolvers/Mutation/createGroupChat.ts b/src/resolvers/Mutation/createGroupChat.ts deleted file mode 100644 index 17dc1548b0..0000000000 --- a/src/resolvers/Mutation/createGroupChat.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, Organization, User } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Creates a new group chat and associates it with a specified organization. - * - * This resolver performs the following actions: - * - * 1. Checks if the specified organization exists in the cache, and if not, fetches it from the database and caches it. - * 2. Verifies that the organization with the given ID exists. - * 3. Checks if each user specified in the `userIds` list exists. - * 4. Creates a new group chat with the specified users, organization, and title. - * - * @param _parent - The parent object, not used in this resolver. - * @param args - The input arguments for the mutation, including: - * - `data`: An object containing: - * - `organizationId`: The ID of the organization to associate with the group chat. - * - `userIds`: A list of user IDs to be added to the group chat. - * - `title`: The title of the group chat. - * @param context - The context object containing user information (context.userId). - * - * @returns A promise that resolves to the created group chat object. - * - * @remarks This function ensures the existence of the organization and users, and caches the organization if it is not already cached. It returns the created group chat object. - */ -export const createGroupChat: MutationResolvers["createGroupChat"] = async ( - _parent, - args, - context, -) => { - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - args.data.organizationId, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: args.data.organizationId, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks whether the organization with _id === args.data.organizationId exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Variable to store list of users to be members of group chat. - const usersInGroupChat = []; - - // Loops over each item in args.data.userIds list. - for await (const userId of args.data.userIds) { - const userExists = !!(await User.exists({ - _id: userId, - })); - - // Checks whether user with _id === userId exists. - if (userExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - usersInGroupChat.push(userId); - } - - // Creates new group chat. - const createdGroupChat = await GroupChat.create({ - creatorId: context.userId, - users: usersInGroupChat, - organization: args.data?.organizationId, - title: args.data?.title, - }); - - // Returns created group chat. - return createdGroupChat.toObject(); -}; diff --git a/src/resolvers/Mutation/createMessageChat.ts b/src/resolvers/Mutation/createMessageChat.ts deleted file mode 100644 index e7d6fdab4c..0000000000 --- a/src/resolvers/Mutation/createMessageChat.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import type { InterfaceAppUserProfile, InterfaceUser } from "../../models"; -import { AppUserProfile, MessageChat, User } from "../../models"; -import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; -import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; - -/** - * Creates a new chat message between users. - * - * This function performs the following actions: - * 1. Verifies the existence of the current user. - * 2. Retrieves and caches the current user's details and application profile if not already cached. - * 3. Checks the existence of the receiver user and retrieves their application profile. - * 4. Ensures that both the current user and the receiver have valid application profiles. - * 5. Compares the language codes of the sender and receiver to determine if there is a language barrier. - * 6. Creates a new chat message with the specified content and language barrier status. - * 7. Publishes the created message chat to a pub/sub channel for real-time updates. - * - * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. - * @param args - The arguments for the mutation, including: - * - `data.receiver`: The ID of the user receiving the message. - * - `data.message`: The content of the message being sent. - * @param context - The context for the mutation, including: - * - `userId`: The ID of the current user sending the message. - * - `pubsub`: The pub/sub instance for publishing real-time updates. - * - * @returns The created message chat record. - * - */ -export const createMessageChat: MutationResolvers["createMessageChat"] = async ( - _parent, - args, - context, -) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - if (!currentUser) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - let currentUserAppProfile: InterfaceAppUserProfile | null; - const appUserProfileFoundInCache = await findAppUserProfileCache([ - currentUser.appUserProfileId?.toString(), - ]); - currentUserAppProfile = appUserProfileFoundInCache[0]; - if (currentUserAppProfile === null) { - currentUserAppProfile = await AppUserProfile.findOne({ - userId: currentUser._id, - }).lean(); - if (currentUserAppProfile !== null) { - await cacheAppUserProfile([currentUserAppProfile]); - } - } - - const receiverUser = await User.findOne({ - _id: args.data.receiver, - }).lean(); - - // Checks whether receiverUser exists. - if (!receiverUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - const receiverUserAppProfile = await AppUserProfile.findOne({ - userId: receiverUser._id, - }).lean(); - if (!receiverUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Boolean to identify whether both sender and receiver for messageChat have the same appLanguageCode. - const isSenderReceiverLanguageSame = - receiverUserAppProfile?.appLanguageCode === - currentUserAppProfile?.appLanguageCode; - - // Creates new messageChat. - const createdMessageChat = await MessageChat.create({ - sender: currentUser?._id, - receiver: receiverUser._id, - message: args.data.message, - languageBarrier: !isSenderReceiverLanguageSame, - }); - - context.pubsub.publish("CHAT_CHANNEL", { - directMessageChat: { - ...createdMessageChat, - }, - }); - - // Returns createdMessageChat. - return createdMessageChat.toObject(); -}; diff --git a/src/resolvers/Mutation/createVolunteerMembership.ts b/src/resolvers/Mutation/createVolunteerMembership.ts new file mode 100644 index 0000000000..e46407c45f --- /dev/null +++ b/src/resolvers/Mutation/createVolunteerMembership.ts @@ -0,0 +1,81 @@ +import { EVENT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR } from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import { Event, User, VolunteerMembership } from "../../models"; +import { EventVolunteer } from "../../models/EventVolunteer"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { checkUserExists } from "../../utilities/checks"; + +/** + * Creates a new event volunteer membership entry. + * + * This function performs the following actions: + * 1. Validates the existence of the current user. + * 2. Checks if the specified user and event exist. + * 3. Creates a new volunteer entry for the event. + * 4. Creates a volunteer membership record for the new volunteer. + * 5. Returns the created vvolunteer membership record. + * + * @param _parent - The parent object for the mutation. This parameter is not used in this resolver. + * @param args - The arguments for the mutation, including: + * - `data.userId`: The ID of the user to be assigned as a volunteer. + * - `data.event`: The ID of the event for which the volunteer is being created. + * - `data.group`: The ID of the volunteer group to which the user is being added. + * - `data.status`: The status of the volunteer membership. + * + * @param context - The context for the mutation, including: + * - `userId`: The ID of the current user performing the operation. + * + * @returns The created event volunteer record. + * + */ +export const createVolunteerMembership: MutationResolvers["createVolunteerMembership"] = + async (_parent, args, context) => { + const { event: eventId, status, group, userId } = args.data; + await checkUserExists(context.userId); + + // Check if the volunteer user exists + const volunteerUser = await User.findById(userId).lean(); + if (!volunteerUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + // Check if the event exists + const event = await Event.findById(eventId).populate("organization").lean(); + if (!event) { + throw new errors.NotFoundError( + requestContext.translate(EVENT_NOT_FOUND_ERROR.MESSAGE), + EVENT_NOT_FOUND_ERROR.CODE, + EVENT_NOT_FOUND_ERROR.PARAM, + ); + } + + // check if event volunteer exists + let eventVolunteer = await EventVolunteer.findOne({ + user: userId, + event: eventId, + }).lean(); + + if (!eventVolunteer) { + // create the volunteer + eventVolunteer = await EventVolunteer.create({ + user: userId, + event: eventId, + creator: context.userId, + groups: [], + }); + } + + // create volunteer membership record + const membership = await VolunteerMembership.create({ + volunteer: eventVolunteer._id, + event: eventId, + status: status, + ...(group && { group }), + createdBy: context.userId, + }); + + return membership.toObject(); + }; diff --git a/src/resolvers/Mutation/index.ts b/src/resolvers/Mutation/index.ts index 390dea99dd..a02bbf2c92 100644 --- a/src/resolvers/Mutation/index.ts +++ b/src/resolvers/Mutation/index.ts @@ -7,10 +7,10 @@ import { addOrganizationCustomField } from "./addOrganizationCustomField"; import { addOrganizationImage } from "./addOrganizationImage"; import { addUserCustomData } from "./addUserCustomData"; import { addUserImage } from "./addUserImage"; -import { addUserToGroupChat } from "./addUserToGroupChat"; import { addUserToUserFamily } from "./addUserToUserFamily"; -import { adminRemoveGroup } from "./adminRemoveGroup"; +import { addPeopleToUserTag } from "./addPeopleToUserTag"; import { assignUserTag } from "./assignUserTag"; +import { assignToUserTags } from "./assignToUserTags"; import { blockPluginCreationBySuperadmin } from "./blockPluginCreationBySuperadmin"; import { blockUser } from "./blockUser"; import { cancelMembershipRequest } from "./cancelMembershipRequest"; @@ -24,7 +24,7 @@ import { createAgendaCategory } from "./createAgendaCategory"; import { createAgendaItem } from "./createAgendaItem"; import { createAgendaSection } from "./createAgendaSection"; import { createComment } from "./createComment"; -import { createDirectChat } from "./createDirectChat"; +import { createChat } from "./createChat"; import { createDonation } from "./createDonation"; import { createEvent } from "./createEvent"; import { createEventVolunteer } from "./createEventVolunteer"; @@ -32,9 +32,7 @@ import { createFund } from "./createFund"; import { createFundraisingCampaign } from "./createFundraisingCampaign"; import { createEventVolunteerGroup } from "./createEventVolunteerGroup"; import { createFundraisingCampaignPledge } from "./createFundraisingCampaignPledge"; -import { createGroupChat } from "./createGroupChat"; import { createMember } from "./createMember"; -import { createMessageChat } from "./createMessageChat"; import { createOrganization } from "./createOrganization"; import { createPlugin } from "./createPlugin"; import { createPost } from "./createPost"; @@ -42,6 +40,7 @@ import { createSampleOrganization } from "./createSampleOrganization"; import { createUserFamily } from "./createUserFamily"; import { createUserTag } from "./createUserTag"; import { createVenue } from "./createVenue"; +import { createVolunteerMembership } from "./createVolunteerMembership"; import { deleteAdvertisement } from "./deleteAdvertisement"; import { deleteAgendaCategory } from "./deleteAgendaCategory"; import { deleteDonationById } from "./deleteDonationById"; @@ -65,13 +64,11 @@ import { removeAdmin } from "./removeAdmin"; import { removeAgendaItem } from "./removeAgendaItem"; import removeAgendaSection from "./removeAgendaSection"; import { removeComment } from "./removeComment"; -import { removeDirectChat } from "./removeDirectChat"; import { removeEvent } from "./removeEvent"; import { removeEventAttendee } from "./removeEventAttendee"; import { removeEventVolunteer } from "./removeEventVolunteer"; import { removeEventVolunteerGroup } from "./removeEventVolunteerGroup"; import { removeFundraisingCampaignPledge } from "./removeFundraisingCampaingPledge"; -import { removeGroupChat } from "./removeGroupChat"; import { removeMember } from "./removeMember"; import { removeOrganization } from "./removeOrganization"; import { removeOrganizationCustomField } from "./removeOrganizationCustomField"; @@ -80,16 +77,15 @@ import { removePost } from "./removePost"; import { removeSampleOrganization } from "./removeSampleOrganization"; import { removeUserCustomData } from "./removeUserCustomData"; import { removeUserFamily } from "./removeUserFamily"; -import { removeUserFromGroupChat } from "./removeUserFromGroupChat"; import { removeUserFromUserFamily } from "./removeUserFromUserFamily"; import { removeUserImage } from "./removeUserImage"; import { removeUserTag } from "./removeUserTag"; +import { removeFromUserTags } from "./removeFromUserTags"; import { resetCommunity } from "./resetCommunity"; import { revokeRefreshTokenForUser } from "./revokeRefreshTokenForUser"; import { saveFcmToken } from "./saveFcmToken"; import { sendMembershipRequest } from "./sendMembershipRequest"; -import { sendMessageToDirectChat } from "./sendMessageToDirectChat"; -import { sendMessageToGroupChat } from "./sendMessageToGroupChat"; +import { sendMessageToChat } from "./sendMessageToChat"; import { signUp } from "./signUp"; import { togglePostPin } from "./togglePostPin"; import { unassignUserTag } from "./unassignUserTag"; @@ -113,11 +109,12 @@ import { updateFundraisingCampaign } from "./updateFundraisingCampaign"; import { updateLanguage } from "./updateLanguage"; import { updateOrganization } from "./updateOrganization"; import { updatePluginStatus } from "./updatePluginStatus"; -import { updatePost } from "./updatePost"; +import { updateSessionTimeout } from "./updateSessionTimeout"; import { updateUserPassword } from "./updateUserPassword"; import { updateUserProfile } from "./updateUserProfile"; import { updateUserRoleInOrganization } from "./updateUserRoleInOrganization"; import { updateUserTag } from "./updateUserTag"; +import { updateVolunteerMembership } from "./updateVolunteerMembership"; import { createNote } from "./createNote"; import { deleteNote } from "./deleteNote"; import { updateNote } from "./updateNote"; @@ -131,13 +128,13 @@ export const Mutation: MutationResolvers = { addOrganizationImage, addUserCustomData, addUserImage, - addUserToGroupChat, - adminRemoveGroup, addUserToUserFamily, + addPeopleToUserTag, + assignUserTag, + assignToUserTags, removeUserFamily, removeUserFromUserFamily, createUserFamily, - assignUserTag, blockPluginCreationBySuperadmin, blockUser, cancelMembershipRequest, @@ -152,13 +149,11 @@ export const Mutation: MutationResolvers = { createAgendaCategory, createAgendaItem, createAgendaSection, - createDirectChat, + createChat, createDonation, createEvent, createFund, createFundraisingCampaign, - createGroupChat, - createMessageChat, createOrganization, createNote, createPlugin, @@ -167,6 +162,7 @@ export const Mutation: MutationResolvers = { createActionItemCategory, createUserTag, createVenue, + createVolunteerMembership, deleteDonationById, deleteAdvertisement, deleteVenue, @@ -193,12 +189,10 @@ export const Mutation: MutationResolvers = { removeAgendaItem, removeAgendaSection, removeComment, - removeDirectChat, removeEvent, removeEventAttendee, removeEventVolunteer, removeEventVolunteerGroup, - removeGroupChat, removeMember, removeOrganization, removeOrganizationCustomField, @@ -206,15 +200,14 @@ export const Mutation: MutationResolvers = { removeSampleOrganization, removePost, removeUserCustomData, - removeUserFromGroupChat, removeUserImage, removeUserTag, + removeFromUserTags, resetCommunity, revokeRefreshTokenForUser, saveFcmToken, sendMembershipRequest, - sendMessageToDirectChat, - sendMessageToGroupChat, + sendMessageToChat, signUp, togglePostPin, unassignUserTag, @@ -236,10 +229,11 @@ export const Mutation: MutationResolvers = { updateLanguage, updateOrganization, updatePluginStatus, + updateSessionTimeout, updateUserProfile, updateUserPassword, updateUserTag, - updatePost, + updateVolunteerMembership, updateAdvertisement, updateFundraisingCampaign, updateFundraisingCampaignPledge, diff --git a/src/resolvers/Mutation/login.ts b/src/resolvers/Mutation/login.ts index cb825c961d..072ead8b62 100644 --- a/src/resolvers/Mutation/login.ts +++ b/src/resolvers/Mutation/login.ts @@ -14,7 +14,7 @@ import { createRefreshToken, } from "../../utilities"; /** - * This function enables login. + * This function enables login. (note: only works when using the last resort SuperAdmin credentials) * @param _parent - parent of current request * @param args - payload provided with the request * @remarks The following checks are done: @@ -55,29 +55,43 @@ export const login: MutationResolvers["login"] = async (_parent, args) => { } let appUserProfile: InterfaceAppUserProfile | null = await AppUserProfile.findOne({ - userId: user._id.toString(), + userId: user._id, appLanguageCode: "en", tokenVersion: 0, }).lean(); if (!appUserProfile) { appUserProfile = await AppUserProfile.create({ - userId: user._id.toString(), + userId: user._id, appLanguageCode: "en", tokenVersion: 0, isSuperAdmin: false, }); - await User.updateOne( + + await User.findOneAndUpdate( { - _id: user._id.toString(), + _id: user._id, }, { - appUserProfileId: appUserProfile?._id?.toString(), + appUserProfileId: appUserProfile?._id, }, + { new: true, lean: true }, ); + + // user = await User.findOne({ + // email: args.data.email.toLowerCase(), + // }).lean(); + + // if (!user) { + // throw new errors.NotFoundError( + // requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + // USER_NOT_FOUND_ERROR.CODE, + // USER_NOT_FOUND_ERROR.PARAM, + // ); + // } } - const accessToken = createAccessToken( + const accessToken = await createAccessToken( user, appUserProfile as InterfaceAppUserProfile, ); @@ -104,7 +118,7 @@ export const login: MutationResolvers["login"] = async (_parent, args) => { // ); await AppUserProfile.findOneAndUpdate( { - user: user._id, + _id: user.appUserProfileId, }, { isSuperAdmin: true, diff --git a/src/resolvers/Mutation/removeDirectChat.ts b/src/resolvers/Mutation/removeDirectChat.ts deleted file mode 100644 index eb1abbe891..0000000000 --- a/src/resolvers/Mutation/removeDirectChat.ts +++ /dev/null @@ -1,81 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { DirectChat, DirectChatMessage, Organization } from "../../models"; -import { adminCheck } from "../../utilities"; -import { errors, requestContext } from "../../libraries"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, -} from "../../constants"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -/** - * This function enables to remove direct chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the organization exists - * 2. If the chat exists - * 3. If the user is an admin of the organization. - * @returns Deleted chat. - */ -export const removeDirectChat: MutationResolvers["removeDirectChat"] = async ( - _parent, - args, - context, -) => { - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - args.organizationId, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: args.organizationId, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - const directChat = await DirectChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks whether directChat exists. - if (!directChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id === context.userId is an admin of organzation. - await adminCheck(context.userId, organization); - - // Deletes all directChatMessages with _id as one of the ids in directChat.messages list. - await DirectChatMessage.deleteMany({ - _id: { - $in: directChat.messages, - }, - }); - - // Deletes the directChat. - await DirectChat.deleteOne({ - _id: args.chatId, - }); - - // Returns deleted directChat. - return directChat; -}; diff --git a/src/resolvers/Mutation/removeEventVolunteer.ts b/src/resolvers/Mutation/removeEventVolunteer.ts index d0b42ebe9e..f375b1ae6a 100644 --- a/src/resolvers/Mutation/removeEventVolunteer.ts +++ b/src/resolvers/Mutation/removeEventVolunteer.ts @@ -1,14 +1,13 @@ import { - EVENT_VOLUNTEER_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import type { InterfaceUser } from "../../models"; -import { EventVolunteer, EventVolunteerGroup, User } from "../../models"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; + EventVolunteer, + EventVolunteerGroup, + VolunteerMembership, +} from "../../models"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { + checkEventVolunteerExists, + checkUserExists, +} from "../../utilities/checks"; /** * This function enables to remove an Event Volunteer. @@ -16,73 +15,33 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; * @param args - payload provided with the request * @param context - context of entire application * @remarks The following checks are done: - * 1. If the current user exists - * 2. If the Event volunteer to be removed exists. - * 3. If the current user is leader of the corresponding event volunteer group. + * 1. If the user exists. + * 2. If the Event Volunteer exists. + * 3. Remove the Event Volunteer from their groups and delete the volunteer. + * 4. Delete the volunteer and their memberships in a single operation. * @returns Event Volunteer. */ export const removeEventVolunteer: MutationResolvers["removeEventVolunteer"] = async (_parent, args, context) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - - if (!currentUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } + await checkUserExists(context.userId); + const volunteer = await checkEventVolunteerExists(args.id); - const volunteer = await EventVolunteer.findOne({ - _id: args.id, - }); + // Remove volunteer from their groups and delete the volunteer + const groupIds = volunteer.groups; - if (!volunteer) { - throw new errors.NotFoundError( - requestContext.translate(EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE), - EVENT_VOLUNTEER_NOT_FOUND_ERROR.CODE, - EVENT_VOLUNTEER_NOT_FOUND_ERROR.PARAM, + if (groupIds.length > 0) { + await EventVolunteerGroup.updateMany( + { _id: { $in: groupIds } }, + { $pull: { volunteers: volunteer._id } }, ); } - const group = await EventVolunteerGroup.findById(volunteer.groupId); - - const userIsLeader = - group?.leaderId.toString() === currentUser._id.toString(); - - if (!userIsLeader) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - await EventVolunteer.deleteOne({ - _id: args.id, - }); - - await EventVolunteerGroup.updateOne( - { - _id: volunteer.groupId, - }, - { - $pull: { - volunteers: volunteer._id, - }, - }, - ); + // Delete the volunteer and their memberships in a single operation + await Promise.all([ + EventVolunteer.deleteOne({ _id: volunteer._id }), + VolunteerMembership.deleteMany({ volunteer: volunteer._id }), + ]); return volunteer; }; diff --git a/src/resolvers/Mutation/removeEventVolunteerGroup.ts b/src/resolvers/Mutation/removeEventVolunteerGroup.ts index 74b072c277..346ff8a4e9 100644 --- a/src/resolvers/Mutation/removeEventVolunteerGroup.ts +++ b/src/resolvers/Mutation/removeEventVolunteerGroup.ts @@ -1,14 +1,20 @@ import { - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, } from "../../constants"; import { errors, requestContext } from "../../libraries"; -import type { InterfaceUser } from "../../models"; -import { Event, EventVolunteer, EventVolunteerGroup, User } from "../../models"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; +import { + Event, + EventVolunteer, + EventVolunteerGroup, + VolunteerMembership, +} from "../../models"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { adminCheck } from "../../utilities"; +import { + checkUserExists, + checkVolunteerGroupExists, +} from "../../utilities/checks"; /** * This function enables to remove an Event Volunteer Group. @@ -24,59 +30,57 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; export const removeEventVolunteerGroup: MutationResolvers["removeEventVolunteerGroup"] = async (_parent, args, context) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } + const currentUser = await checkUserExists(context.userId); + const volunteerGroup = await checkVolunteerGroupExists(args.id); - if (!currentUser) { + const event = await Event.findById(volunteerGroup.event) + .populate("organization") + .lean(); + if (!event) { throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, + requestContext.translate(EVENT_NOT_FOUND_ERROR.MESSAGE), + EVENT_NOT_FOUND_ERROR.CODE, + EVENT_NOT_FOUND_ERROR.PARAM, ); } - const volunteerGroup = await EventVolunteerGroup.findOne({ - _id: args.id, - }); - - if (!volunteerGroup) { - throw new errors.NotFoundError( - requestContext.translate(EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE), - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.CODE, - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.PARAM, - ); - } - - const event = await Event.findById(volunteerGroup.eventId); - - const userIsEventAdmin = event?.admins.some( - (admin) => admin._id.toString() === currentUser?._id.toString(), + const userIsEventAdmin = event.admins.some( + (admin) => admin.toString() === currentUser?._id.toString(), ); - if (!userIsEventAdmin) { - throw new errors.NotFoundError( + const isAdmin = await adminCheck( + currentUser._id, + event.organization, + false, + ); + // Checks if user is Event Admin or Admin of the organization + if (!isAdmin && !userIsEventAdmin) { + throw new errors.UnauthorizedError( requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), USER_NOT_AUTHORIZED_ERROR.CODE, USER_NOT_AUTHORIZED_ERROR.PARAM, ); } - await EventVolunteerGroup.deleteOne({ - _id: args.id, - }); + await Promise.all([ + // Remove the volunteer group + EventVolunteerGroup.deleteOne({ _id: args.id }), + + // Remove the group from volunteers + EventVolunteer.updateMany( + { groups: { $in: args.id } }, + { $pull: { groups: args.id } }, + ), + + // Delete all associated volunteer group memberships + VolunteerMembership.deleteMany({ group: args.id }), - await EventVolunteer.deleteMany({ - groupId: args.id, - }); + // Remove the group from the event + Event.updateOne( + { _id: volunteerGroup.event }, + { $pull: { volunteerGroups: args.id } }, + ), + ]); return volunteerGroup; }; diff --git a/src/resolvers/Mutation/removeFromUserTags.ts b/src/resolvers/Mutation/removeFromUserTags.ts new file mode 100644 index 0000000000..0420f5fbb5 --- /dev/null +++ b/src/resolvers/Mutation/removeFromUserTags.ts @@ -0,0 +1,165 @@ +import { Types } from "mongoose"; +import { + TAG_NOT_FOUND, + USER_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_ERROR, +} from "../../constants"; +import { errors, requestContext } from "../../libraries"; +import type { InterfaceAppUserProfile, InterfaceUser } from "../../models"; +import { + AppUserProfile, + OrganizationTagUser, + TagUser, + User, +} from "../../models"; +import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; +import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; +import { cacheUsers } from "../../services/UserCache/cacheUser"; +import { findUserInCache } from "../../services/UserCache/findUserInCache"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; + +/** + * This function enables an admin to remove multiple tags from users with a specified tag. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the current user exists and has a profile. + * 2. If the current user is an admin for the organization of the tags. + * 3. If the currentTagId exists and the selected tags exist. + * 4. Remove the tags from users who have the currentTagId. + * @returns Array of tags that were removed from users. + */ +export const removeFromUserTags: MutationResolvers["removeFromUserTags"] = + async (_parent, args, context) => { + let currentUser: InterfaceUser | null; + const userFoundInCache = await findUserInCache([context.userId]); + currentUser = userFoundInCache[0]; + if (currentUser === null) { + currentUser = await User.findOne({ + _id: context.userId, + }).lean(); + if (currentUser !== null) { + await cacheUsers([currentUser]); + } + } + + // Checks whether the currentUser exists. + if (!currentUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + let currentUserAppProfile: InterfaceAppUserProfile | null; + + const appUserProfileFoundInCache = await findAppUserProfileCache([ + currentUser.appUserProfileId.toString(), + ]); + + currentUserAppProfile = appUserProfileFoundInCache[0]; + if (currentUserAppProfile === null) { + currentUserAppProfile = await AppUserProfile.findOne({ + userId: currentUser._id, + }).lean(); + if (currentUserAppProfile !== null) { + await cacheAppUserProfile([currentUserAppProfile]); + } + } + + if (!currentUserAppProfile) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Get the current tag object + const currentTag = await OrganizationTagUser.findOne({ + _id: args.input.currentTagId, + }).lean(); + + if (!currentTag) { + throw new errors.NotFoundError( + requestContext.translate(TAG_NOT_FOUND.MESSAGE), + TAG_NOT_FOUND.CODE, + TAG_NOT_FOUND.PARAM, + ); + } + + // Boolean to determine whether user is an admin of the organization of the current tag. + const currentUserIsOrganizationAdmin = currentUserAppProfile.adminFor.some( + (orgId) => orgId?.toString() === currentTag.organizationId.toString(), + ); + + if ( + !(currentUserIsOrganizationAdmin || currentUserAppProfile.isSuperAdmin) + ) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + + // Find selected tags & all users tagged with the current tag + const [selectedTags, usersWithCurrentTag] = await Promise.all([ + OrganizationTagUser.find({ + _id: { $in: args.input.selectedTagIds }, + }).lean(), + TagUser.find({ tagId: currentTag._id }).lean(), + ]); + + const userIdsWithCurrentTag = usersWithCurrentTag.map( + (userTag) => userTag.userId, + ); + + if (selectedTags.length !== args.input.selectedTagIds.length) { + throw new errors.NotFoundError( + requestContext.translate(TAG_NOT_FOUND.MESSAGE), + TAG_NOT_FOUND.CODE, + TAG_NOT_FOUND.PARAM, + ); + } + + // Get all descendant tags of the selected tags (including the selected tags themselves) + const allTagsToRemove = new Set(); + let currentParents = selectedTags.map((tag) => tag._id.toString()); + + while (currentParents.length > 0) { + // Add the current level of tags to the set + for (const parentId of currentParents) { + allTagsToRemove.add(parentId); + } + + // Find the next level of child tags + const childTags = await OrganizationTagUser.find( + { + parentTagId: { $in: currentParents }, + }, + { _id: 1 }, + ).lean(); + + // Update currentParents with the next level of children + currentParents = childTags.map((tag) => tag._id.toString()); + } + + // Now allTagsToRemove contains all descendants of the selected tags + + const tagUserDocs = userIdsWithCurrentTag.flatMap((userId) => + Array.from(allTagsToRemove).map((tagId) => ({ + deleteOne: { + filter: { userId, tagId: new Types.ObjectId(tagId) }, + }, + })), + ); + + if (tagUserDocs.length > 0) { + await TagUser.bulkWrite(tagUserDocs); + } + + return currentTag; + }; diff --git a/src/resolvers/Mutation/removeGroupChat.ts b/src/resolvers/Mutation/removeGroupChat.ts deleted file mode 100644 index 7509d3fa20..0000000000 --- a/src/resolvers/Mutation/removeGroupChat.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { adminCheck } from "../../utilities"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, -} from "../../constants"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, GroupChatMessage, Organization } from "../../models"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -/** - * This function enables to remove an graoup chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the group chat exists - * 2. If the organization exists - * 3. If the user is an admin of the organization. - * @returns Deleted group chat. - */ -export const removeGroupChat: MutationResolvers["removeGroupChat"] = async ( - _parent, - args, - context, -) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks if a groupChat with _id === args.chatId exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache.includes(null)) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks if an organization with _id === groupChat.organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether current user making the request is an admin of organization. - await adminCheck(context.userId, organization); - - // Delete all groupChatMessages that have their ids stored in messages list of groupChat - await GroupChatMessage.deleteMany({ - _id: { - $in: groupChat.messages, - }, - }); - - // Delete the groupChat - await GroupChat.deleteOne({ - _id: groupChat._id, - }); - - return groupChat; -}; diff --git a/src/resolvers/Mutation/removePost.ts b/src/resolvers/Mutation/removePost.ts index 96669acd6d..cfc22f7809 100644 --- a/src/resolvers/Mutation/removePost.ts +++ b/src/resolvers/Mutation/removePost.ts @@ -18,8 +18,7 @@ import { findPostsInCache } from "../../services/PostCache/findPostsInCache"; import { cacheUsers } from "../../services/UserCache/cacheUser"; import { findUserInCache } from "../../services/UserCache/findUserInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { deletePreviousImage as deleteImage } from "../../utilities/encodedImageStorage/deletePreviousImage"; -import { deletePreviousVideo as deleteVideo } from "../../utilities/encodedVideoStorage/deletePreviousVideo"; +import { deletePreviousFile as deleteFile } from "../../utilities/encodedImageStorage/deletePreviousFile"; import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; /** @@ -125,18 +124,18 @@ export const removePost: MutationResolvers["removePost"] = async ( // Deletes the post. const deletedPost = await Post.findOneAndDelete({ _id: args.id, - }); + }) + .populate({ path: "file", select: "_id metadata.objectKey" }) + .lean(); await deletePostFromCache(args.id); - //deletes the image in post - if (deletedPost?.imageUrl) { - await deleteImage(deletedPost?.imageUrl); - } - - //deletes the video in post - if (deletedPost?.videoUrl) { - await deleteVideo(deletedPost?.videoUrl); + // Deletes the media in the post + if (deletedPost?.file) { + await deleteFile( + deletedPost.file._id.toString(), + deletedPost.file.metadata.objectKey, + ); } // Removes the post from the organization, doesn't fail if the post wasn't pinned diff --git a/src/resolvers/Mutation/removeUserFromGroupChat.ts b/src/resolvers/Mutation/removeUserFromGroupChat.ts deleted file mode 100644 index fea9d35e00..0000000000 --- a/src/resolvers/Mutation/removeUserFromGroupChat.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, -} from "../../constants"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, Organization } from "../../models"; -import { adminCheck } from "../../utilities"; -import { cacheOrganizations } from "../../services/OrganizationCache/cacheOrganizations"; -import { findOrganizationsInCache } from "../../services/OrganizationCache/findOrganizationsInCache"; -import type { InterfaceGroupChat } from "../../models"; -/** - * This function enables to remove a user from group chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the group chat exists. - * 2. If the organization exists - * 3. If the user is the admin of the organization. - * 4. If the user to be removed is a member of the organization. - * @returns Updated group chat. - */ -export const removeUserFromGroupChat: MutationResolvers["removeUserFromGroupChat"] = - async (_parent, args, context) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - // Checks whether groupChat exists. - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - let organization; - - const organizationFoundInCache = await findOrganizationsInCache([ - groupChat.organization, - ]); - - organization = organizationFoundInCache[0]; - - if (organizationFoundInCache[0] == null) { - organization = await Organization.findOne({ - _id: groupChat.organization, - }).lean(); - if (organization) await cacheOrganizations([organization]); - } - - // Checks whether organization exists. - if (!organization) { - throw new errors.NotFoundError( - requestContext.translate(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE), - ORGANIZATION_NOT_FOUND_ERROR.CODE, - ORGANIZATION_NOT_FOUND_ERROR.PARAM, - ); - } - - // Checks whether currentUser with _id == context.userId is an admin of organzation. - await adminCheck(context.userId, organization); - - const userIsMemberOfGroupChat = groupChat.users.some((user) => - user.equals(args.userId), - ); - - // Checks if user with _id === args.userId is not a member of groupChat. - if (userIsMemberOfGroupChat === false) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Removes args.userId from users list of groupChat and returns the updated groupChat. - return (await GroupChat.findOneAndUpdate( - { - _id: args.chatId, - }, - { - $set: { - users: groupChat.users.filter( - (user) => user.toString() !== args.userId.toString(), - ), - }, - }, - { - new: true, - }, - ).lean()) as InterfaceGroupChat; - }; diff --git a/src/resolvers/Mutation/sendMembershipRequest.ts b/src/resolvers/Mutation/sendMembershipRequest.ts index cd4e94767b..12dadc1587 100644 --- a/src/resolvers/Mutation/sendMembershipRequest.ts +++ b/src/resolvers/Mutation/sendMembershipRequest.ts @@ -78,8 +78,9 @@ export const sendMembershipRequest: MutationResolvers["sendMembershipRequest"] = // Checks if the user is blocked const user = await User.findById(context.userId).lean(); + if ( - user !== null && + user != null && organization.blockedUsers.some((blockedUser) => new mongoose.Types.ObjectId(blockedUser.toString()).equals(user._id), ) @@ -96,8 +97,24 @@ export const sendMembershipRequest: MutationResolvers["sendMembershipRequest"] = user: context.userId, organization: organization._id, }); - if (membershipRequestExists) { + // Check if the request is already in the user's document + if ( + user != null && + !user.membershipRequests.includes(membershipRequestExists._id) + ) { + // If it's not in the user's document, add it + await User.findByIdAndUpdate( + context.userId, + { + $push: { + membershipRequests: membershipRequestExists._id, + }, + }, + { new: true, runValidators: true }, + ); + } + throw new errors.ConflictError( requestContext.translate(MEMBERSHIP_REQUEST_ALREADY_EXISTS.MESSAGE), MEMBERSHIP_REQUEST_ALREADY_EXISTS.CODE, @@ -105,12 +122,13 @@ export const sendMembershipRequest: MutationResolvers["sendMembershipRequest"] = ); } + // Creating Membership Request const createdMembershipRequest = await MembershipRequest.create({ user: context.userId, organization: organization._id, }); - // add membership request to organization + // Updating Membership Request in organization const updatedOrganization = await Organization.findOneAndUpdate( { _id: organization._id, @@ -129,16 +147,15 @@ export const sendMembershipRequest: MutationResolvers["sendMembershipRequest"] = await cacheOrganizations([updatedOrganization]); } - // add membership request to user - await User.updateOne( - { - _id: context.userId, - }, + // Updating User + await User.findByIdAndUpdate( + context.userId, { $push: { membershipRequests: createdMembershipRequest._id, }, }, + { new: true, runValidators: true }, ); return createdMembershipRequest.toObject(); diff --git a/src/resolvers/Mutation/sendMessageToChat.ts b/src/resolvers/Mutation/sendMessageToChat.ts new file mode 100644 index 0000000000..24145efbd0 --- /dev/null +++ b/src/resolvers/Mutation/sendMessageToChat.ts @@ -0,0 +1,73 @@ +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { errors, requestContext } from "../../libraries"; +import { Chat, User, ChatMessage } from "../../models"; +import { CHAT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR } from "../../constants"; +/** + * This function enables to send message to chat. + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. If the direct chat exists. + * 2. If the user exists + * @returns Chat message. + */ +export const sendMessageToChat: MutationResolvers["sendMessageToChat"] = async ( + _parent, + args, + context, +) => { + const chat = await Chat.findOne({ + _id: args.chatId, + }).lean(); + + if (!chat) { + throw new errors.NotFoundError( + requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), + CHAT_NOT_FOUND_ERROR.CODE, + CHAT_NOT_FOUND_ERROR.PARAM, + ); + } + + const currentUserExists = !!(await User.exists({ + _id: context.userId, + })); + + if (currentUserExists === false) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + const now = new Date(); + + const createdChatMessage = await ChatMessage.create({ + chatMessageBelongsTo: chat._id, + sender: context.userId, + messageContent: args.messageContent, + replyTo: args.replyTo, + createdAt: now, + updatedAt: now, + }); + + // add createdChatMessage to Chat + await Chat.updateOne( + { + _id: chat._id, + }, + { + $push: { + messages: createdChatMessage._id, + }, + }, + ); + + // calls subscription + context.pubsub.publish("MESSAGE_SENT_TO_CHAT", { + messageSentToChat: createdChatMessage.toObject(), + }); + + return createdChatMessage.toObject(); +}; diff --git a/src/resolvers/Mutation/sendMessageToDirectChat.ts b/src/resolvers/Mutation/sendMessageToDirectChat.ts deleted file mode 100644 index 65cbf15f2b..0000000000 --- a/src/resolvers/Mutation/sendMessageToDirectChat.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { DirectChat, DirectChatMessage, User } from "../../models"; -import { CHAT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR } from "../../constants"; -/** - * This function enables to send message to direct chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the direct chat exists. - * 2. If the user exists - * @returns Direct chat message. - */ -export const sendMessageToDirectChat: MutationResolvers["sendMessageToDirectChat"] = - async (_parent, args, context) => { - const directChat = await DirectChat.findOne({ - _id: args.chatId, - }).lean(); - - if (!directChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserExists = !!(await User.exists({ - _id: context.userId, - })); - - if (currentUserExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - // directChat.users can only have 2 users. So, the following method works. - const receiverIndex = directChat.users.findIndex( - (user) => user.toString() !== context.userId.toString(), - ); - - const createdDirectChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: directChat._id, - sender: context.userId, - receiver: directChat.users[receiverIndex], - messageContent: args.messageContent, - }); - - // add createdDirectChatMessage to directChat - await DirectChat.updateOne( - { - _id: directChat._id, - }, - { - $push: { - messages: createdDirectChatMessage._id, - }, - }, - ); - - // calls subscription - context.pubsub.publish("MESSAGE_SENT_TO_DIRECT_CHAT", { - messageSentToDirectChat: createdDirectChatMessage.toObject(), - }); - - return createdDirectChatMessage.toObject(); - }; diff --git a/src/resolvers/Mutation/sendMessageToGroupChat.ts b/src/resolvers/Mutation/sendMessageToGroupChat.ts deleted file mode 100644 index 93d9f7d5dd..0000000000 --- a/src/resolvers/Mutation/sendMessageToGroupChat.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { errors, requestContext } from "../../libraries"; -import { GroupChat, GroupChatMessage, User } from "../../models"; -import { - USER_NOT_AUTHORIZED_ERROR, - CHAT_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -/** - * This function enables to send message to group chat. - * @param _parent - parent of current request - * @param args - payload provided with the request - * @param context - context of entire application - * @remarks The following checks are done: - * 1. If the group chat exists. - * 2. If the user exists - * 3. If the group chat contains the user. - * @returns Group chat message. - */ -export const sendMessageToGroupChat: MutationResolvers["sendMessageToGroupChat"] = - async (_parent, args, context) => { - const groupChat = await GroupChat.findOne({ - _id: args.chatId, - }).lean(); - - if (!groupChat) { - throw new errors.NotFoundError( - requestContext.translate(CHAT_NOT_FOUND_ERROR.MESSAGE), - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserExists = !!(await User.exists({ - _id: context.userId, - })); - - if (currentUserExists === false) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - const currentUserIsAMemberOfGroupChat = groupChat.users.some((user) => - user.equals(context.userId), - ); - - /* - checks if users list of groupChat with _id === args.chatId contains - current user with _id === context.userId - */ - if (currentUserIsAMemberOfGroupChat === false) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - const createdGroupChatMessage = await GroupChatMessage.create({ - groupChatMessageBelongsTo: groupChat._id, - sender: context.userId, - createdAt: new Date(), - messageContent: args.messageContent, - }); - - // add createdGroupChatMessage to groupChat - await GroupChat.updateOne( - { - _id: args.chatId, - }, - { - $push: { - messages: createdGroupChatMessage._id, - }, - }, - ); - - // calls subscription - context.pubsub.publish("MESSAGE_SENT_TO_GROUP_CHAT", { - messageSentToGroupChat: createdGroupChatMessage.toObject(), - }); - - return createdGroupChatMessage.toObject(); - }; diff --git a/src/resolvers/Mutation/updateActionItem.ts b/src/resolvers/Mutation/updateActionItem.ts index 265a40104c..555cb82433 100644 --- a/src/resolvers/Mutation/updateActionItem.ts +++ b/src/resolvers/Mutation/updateActionItem.ts @@ -2,45 +2,54 @@ import mongoose from "mongoose"; import { ACTION_ITEM_NOT_FOUND_ERROR, EVENT_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, USER_NOT_FOUND_ERROR, - USER_NOT_MEMBER_FOR_ORGANIZATION, } from "../../constants"; import { errors, requestContext } from "../../libraries"; import type { - InterfaceAppUserProfile, InterfaceEvent, + InterfaceEventVolunteer, + InterfaceEventVolunteerGroup, InterfaceUser, } from "../../models"; -import { ActionItem, AppUserProfile, Event, User } from "../../models"; -import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; -import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; +import { + ActionItem, + Event, + EventVolunteer, + EventVolunteerGroup, + User, +} from "../../models"; import { cacheEvents } from "../../services/EventCache/cacheEvents"; import { findEventsInCache } from "../../services/EventCache/findEventInCache"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { + checkAppUserProfileExists, + checkUserExists, +} from "../../utilities/checks"; /** * This function enables to update an action item. * @param _parent - parent of current request * @param args - payload provided with the request * @param context - context of entire application * @remarks The following checks are done: - * 1. If the user exists. - * 2. If the new asignee exists. - * 2. If the action item exists. - * 4. If the new asignee is a member of the organization. - * 5. If the user is authorized. - * 6. If the user has appUserProfile. + * 1. Whether the user exists + * 2. Whether the user has an associated app user profile + * 3. Whether the action item exists + * 4. Whether the user is authorized to update the action item + * 5. Whether the user is an admin of the organization or a superadmin + * * @returns Updated action item. */ type UpdateActionItemInputType = { assigneeId: string; + assigneeType: string; preCompletionNotes: string; postCompletionNotes: string; dueDate: Date; - allotedHours: number; + allottedHours: number; completionDate: Date; isCompleted: boolean; }; @@ -50,46 +59,9 @@ export const updateActionItem: MutationResolvers["updateActionItem"] = async ( args, context, ) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - - // Checks if the user exists - if (currentUser === null) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - let currentUserAppProfile: InterfaceAppUserProfile | null; - const appUserProfileFoundInCache = await findAppUserProfileCache([ - currentUser.appUserProfileId?.toString(), - ]); - currentUserAppProfile = appUserProfileFoundInCache[0]; - if (currentUserAppProfile === null) { - currentUserAppProfile = await AppUserProfile.findOne({ - userId: currentUser._id, - }).lean(); - if (currentUserAppProfile !== null) { - await cacheAppUserProfile([currentUserAppProfile]); - } - } - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } + const currentUser = await checkUserExists(context.userId); + const currentUserAppProfile = await checkAppUserProfileExists(currentUser); + const { assigneeId, assigneeType, isCompleted } = args.data; const actionItem = await ActionItem.findOne({ _id: args.id, @@ -106,44 +78,54 @@ export const updateActionItem: MutationResolvers["updateActionItem"] = async ( ); } - let sameAssignedUser = false; + let sameAssignee = false; - if (args.data.assigneeId) { - sameAssignedUser = new mongoose.Types.ObjectId( - actionItem.assignee.toString(), - ).equals(args.data.assigneeId); + if (assigneeId) { + sameAssignee = new mongoose.Types.ObjectId( + assigneeType === "EventVolunteer" + ? actionItem.assignee.toString() + : assigneeType === "EventVolunteerGroup" + ? actionItem.assigneeGroup.toString() + : actionItem.assigneeUser.toString(), + ).equals(assigneeId); - if (!sameAssignedUser) { - const newAssignedUser = await User.findOne({ - _id: args.data.assigneeId, - }); - - // Checks if the new asignee exists - if (newAssignedUser === null) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - let userIsOrganizationMember = false; - const currorganizationId = actionItem.actionItemCategory.organizationId; - userIsOrganizationMember = newAssignedUser.joinedOrganizations.some( - (organizationId) => - organizationId === currorganizationId || - new mongoose.Types.ObjectId(organizationId.toString()).equals( - currorganizationId, - ), - ); - - // Checks if the new asignee is a member of the organization - if (!userIsOrganizationMember) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE), - USER_NOT_MEMBER_FOR_ORGANIZATION.CODE, - USER_NOT_MEMBER_FOR_ORGANIZATION.PARAM, - ); + if (!sameAssignee) { + let assignee: + | InterfaceEventVolunteer + | InterfaceEventVolunteerGroup + | InterfaceUser + | null; + if (assigneeType === "EventVolunteer") { + assignee = await EventVolunteer.findById(assigneeId) + .populate("user") + .lean(); + if (!assignee) { + throw new errors.NotFoundError( + requestContext.translate(EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE), + EVENT_VOLUNTEER_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_NOT_FOUND_ERROR.PARAM, + ); + } + } else if (assigneeType === "EventVolunteerGroup") { + assignee = await EventVolunteerGroup.findById(assigneeId).lean(); + if (!assignee) { + throw new errors.NotFoundError( + requestContext.translate( + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, + ), + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.PARAM, + ); + } + } else if (assigneeType === "User") { + assignee = await User.findById(assigneeId).lean(); + if (!assignee) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } } } } @@ -192,8 +174,9 @@ export const updateActionItem: MutationResolvers["updateActionItem"] = async ( ); } - // Checks if the user is authorized for the operation. + // Checks if the user is authorized for the operation. (Exception: when user updates the action item to complete or incomplete) if ( + isCompleted === undefined && currentUserIsEventAdmin === false && currentUserIsOrgAdmin === false && currentUserAppProfile.isSuperAdmin === false @@ -205,13 +188,102 @@ export const updateActionItem: MutationResolvers["updateActionItem"] = async ( ); } - const updatedAssignmentDate = sameAssignedUser + // checks if the assignee is an event volunteer then add allotted hours to the volunteer else if event volunteer group then add divided equal allotted hours to all volunteers in the group + + if (assigneeType === "EventVolunteer") { + const assignee = await EventVolunteer.findById(assigneeId).lean(); + if (assignee) { + if (isCompleted == true) { + await EventVolunteer.findByIdAndUpdate(assigneeId, { + $inc: { + hoursVolunteered: actionItem.allottedHours + ? actionItem.allottedHours + : 0, + }, + ...(actionItem.allottedHours + ? { + $push: { + hoursHistory: { + hours: actionItem.allottedHours, + date: new Date(), + }, + }, + } + : {}), + }); + } else if (isCompleted == false) { + await EventVolunteer.findByIdAndUpdate(assigneeId, { + $inc: { + hoursVolunteered: actionItem.allottedHours + ? -actionItem.allottedHours + : -0, + }, + ...(actionItem.allottedHours + ? { + $push: { + hoursHistory: { + hours: -actionItem.allottedHours, + date: new Date(), + }, + }, + } + : {}), + }); + } + } + } else if (assigneeType === "EventVolunteerGroup") { + const volunteerGroup = + await EventVolunteerGroup.findById(assigneeId).lean(); + if (volunteerGroup) { + const dividedHours = + (actionItem.allottedHours ?? 0) / volunteerGroup.volunteers.length; + if (isCompleted == true) { + await EventVolunteer.updateMany( + { _id: { $in: volunteerGroup.volunteers } }, + { + $inc: { + hoursVolunteered: dividedHours, + }, + ...(dividedHours + ? { + $push: { + hoursHistory: { + hours: dividedHours, + date: new Date(), + }, + }, + } + : {}), + }, + ); + } else if (isCompleted == false) { + await EventVolunteer.updateMany( + { _id: { $in: volunteerGroup.volunteers } }, + { + $inc: { + hoursVolunteered: -dividedHours, + }, + ...(dividedHours + ? { + $push: { + hoursHistory: { + hours: dividedHours, + date: new Date(), + }, + }, + } + : {}), + }, + ); + } + } + } + + const updatedAssignmentDate = sameAssignee ? actionItem.assignmentDate : new Date(); - const updatedAssigner = sameAssignedUser - ? actionItem.assigner - : context.userId; + const updatedAssigner = sameAssignee ? actionItem.assigner : context.userId; const updatedActionItem = await ActionItem.findOneAndUpdate( { @@ -219,7 +291,25 @@ export const updateActionItem: MutationResolvers["updateActionItem"] = async ( }, { ...(args.data as UpdateActionItemInputType), - assignee: args.data.assigneeId || actionItem.assignee, + assigneeType: assigneeType || actionItem.assigneeType, + assignee: + !sameAssignee && assigneeType === "EventVolunteer" + ? assigneeId || actionItem.assignee + : isCompleted === undefined + ? null + : actionItem.assignee, + assigneeGroup: + !sameAssignee && assigneeType === "EventVolunteerGroup" + ? assigneeId || actionItem.assigneeGroup + : isCompleted === undefined + ? null + : actionItem.assigneeGroup, + assigneeUser: + !sameAssignee && assigneeType === "User" + ? assigneeId || actionItem.assigneeUser + : isCompleted === undefined + ? null + : actionItem.assigneeUser, assignmentDate: updatedAssignmentDate, assigner: updatedAssigner, }, diff --git a/src/resolvers/Mutation/updateAgendaCategory.ts b/src/resolvers/Mutation/updateAgendaCategory.ts index cf2c523930..82105f8c64 100644 --- a/src/resolvers/Mutation/updateAgendaCategory.ts +++ b/src/resolvers/Mutation/updateAgendaCategory.ts @@ -117,7 +117,7 @@ export const updateAgendaCategory: MutationResolvers["updateAgendaCategory"] = { $set: { updatedBy: context.userId, - // eslint-disable-next-line + ...(args.input as UpdateAgendaCategoryInput), }, }, diff --git a/src/resolvers/Mutation/updateEventVolunteer.ts b/src/resolvers/Mutation/updateEventVolunteer.ts index 68d5cdbdbb..6aa7946b1f 100644 --- a/src/resolvers/Mutation/updateEventVolunteer.ts +++ b/src/resolvers/Mutation/updateEventVolunteer.ts @@ -1,15 +1,12 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import type { EventVolunteerResponse } from "../../constants"; -import { - EVENT_VOLUNTEER_INVITE_USER_MISTMATCH, - EVENT_VOLUNTEER_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import type { InterfaceEventVolunteer, InterfaceUser } from "../../models"; -import { User, EventVolunteer } from "../../models"; +import { EVENT_VOLUNTEER_INVITE_USER_MISTMATCH } from "../../constants"; +import type { InterfaceEventVolunteer } from "../../models"; +import { EventVolunteer } from "../../models"; import { errors, requestContext } from "../../libraries"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; +import { + checkEventVolunteerExists, + checkUserExists, +} from "../../utilities/checks"; /** * This function enables to update an Event Volunteer * @param _parent - parent of current request @@ -19,43 +16,14 @@ import { cacheUsers } from "../../services/UserCache/cacheUser"; * 1. Whether the user exists * 2. Whether the EventVolunteer exists * 3. Whether the current user is the user of EventVolunteer - * 4. Whether the EventVolunteer is invited + * 4. Update the EventVolunteer */ export const updateEventVolunteer: MutationResolvers["updateEventVolunteer"] = async (_parent, args, context) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - - if (!currentUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - const eventVolunteer = await EventVolunteer.findOne({ - _id: args.id, - }).lean(); - - if (!eventVolunteer) { - throw new errors.NotFoundError( - requestContext.translate(EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE), - EVENT_VOLUNTEER_NOT_FOUND_ERROR.CODE, - EVENT_VOLUNTEER_NOT_FOUND_ERROR.PARAM, - ); - } + await checkUserExists(context.userId); + const volunteer = await checkEventVolunteerExists(args.id); - if (eventVolunteer.userId.toString() !== context.userId.toString()) { + if (volunteer.user.toString() !== context.userId.toString()) { throw new errors.ConflictError( requestContext.translate(EVENT_VOLUNTEER_INVITE_USER_MISTMATCH.MESSAGE), EVENT_VOLUNTEER_INVITE_USER_MISTMATCH.CODE, @@ -69,22 +37,18 @@ export const updateEventVolunteer: MutationResolvers["updateEventVolunteer"] = }, { $set: { - eventId: - args.data?.eventId === undefined - ? eventVolunteer.eventId - : (args?.data.eventId as string), - isAssigned: - args.data?.isAssigned === undefined - ? eventVolunteer.isAssigned - : (args.data?.isAssigned as boolean), - isInvited: - args.data?.isInvited === undefined - ? eventVolunteer.isInvited - : (args.data?.isInvited as boolean), - response: - args.data?.response === undefined - ? eventVolunteer.response - : (args.data?.response as EventVolunteerResponse), + assignments: + args.data?.assignments === undefined + ? volunteer.assignments + : (args.data?.assignments as string[]), + hasAccepted: + args.data?.hasAccepted === undefined + ? volunteer.hasAccepted + : (args.data?.hasAccepted as boolean), + isPublic: + args.data?.isPublic === undefined + ? volunteer.isPublic + : (args.data?.isPublic as boolean), }, }, { diff --git a/src/resolvers/Mutation/updateEventVolunteerGroup.ts b/src/resolvers/Mutation/updateEventVolunteerGroup.ts index e7c67290d4..1abb7112f9 100644 --- a/src/resolvers/Mutation/updateEventVolunteerGroup.ts +++ b/src/resolvers/Mutation/updateEventVolunteerGroup.ts @@ -1,14 +1,14 @@ import { + EVENT_NOT_FOUND_ERROR, EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, } from "../../constants"; import { errors, requestContext } from "../../libraries"; -import type { InterfaceEventVolunteerGroup, InterfaceUser } from "../../models"; -import { EventVolunteerGroup, User } from "../../models"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; +import type { InterfaceEventVolunteerGroup } from "../../models"; +import { Event, EventVolunteerGroup } from "../../models"; import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { adminCheck } from "../../utilities"; +import { checkUserExists } from "../../utilities/checks"; /** * This function enables to update the Event Volunteer Group * @param _parent - parent of current request @@ -21,26 +21,28 @@ import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; */ export const updateEventVolunteerGroup: MutationResolvers["updateEventVolunteerGroup"] = async (_parent, args, context) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - - if (!currentUser) { + const { eventId, description, name, volunteersRequired } = args.data; + const currentUser = await checkUserExists(context.userId); + const event = await Event.findById(eventId).populate("organization").lean(); + if (!event) { throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, + requestContext.translate(EVENT_NOT_FOUND_ERROR.MESSAGE), + EVENT_NOT_FOUND_ERROR.CODE, + EVENT_NOT_FOUND_ERROR.PARAM, ); } + const userIsEventAdmin = event.admins.some( + (admin: { toString: () => string }) => + admin.toString() === currentUser?._id.toString(), + ); + + const isAdmin = await adminCheck( + currentUser._id, + event.organization, + false, + ); + const group = await EventVolunteerGroup.findOne({ _id: args.id, }).lean(); @@ -53,7 +55,12 @@ export const updateEventVolunteerGroup: MutationResolvers["updateEventVolunteerG ); } - if (group.leaderId.toString() !== context.userId.toString()) { + // Checks if user is Event Admin or Admin of the organization or Leader of the group + if ( + !isAdmin && + !userIsEventAdmin && + group.leader.toString() !== currentUser._id.toString() + ) { throw new errors.UnauthorizedError( requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), USER_NOT_AUTHORIZED_ERROR.CODE, @@ -67,20 +74,13 @@ export const updateEventVolunteerGroup: MutationResolvers["updateEventVolunteerG }, { $set: { - eventId: - args.data?.eventId === undefined - ? group.eventId - : args?.data.eventId, - name: args.data?.name === undefined ? group.name : args?.data.name, - volunteersRequired: - args.data?.volunteersRequired === undefined - ? group.volunteersRequired - : args?.data.volunteersRequired, + description, + name, + volunteersRequired, }, }, { new: true, - runValidators: true, }, ).lean(); diff --git a/src/resolvers/Mutation/updatePost.ts b/src/resolvers/Mutation/updatePost.ts deleted file mode 100644 index 82d3669a20..0000000000 --- a/src/resolvers/Mutation/updatePost.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { Types } from "mongoose"; -import { - LENGTH_VALIDATION_ERROR, - PLEASE_PROVIDE_TITLE, - POST_NEEDS_TO_BE_PINNED, - POST_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../constants"; -import { errors, requestContext } from "../../libraries"; -import { isValidString } from "../../libraries/validators/validateString"; -import type { - InterfaceAppUserProfile, - InterfacePost, - InterfaceUser, -} from "../../models"; -import { AppUserProfile, Post, User } from "../../models"; -import { cachePosts } from "../../services/PostCache/cachePosts"; -import { findPostsInCache } from "../../services/PostCache/findPostsInCache"; -import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; -import { uploadEncodedImage } from "../../utilities/encodedImageStorage/uploadEncodedImage"; -import { uploadEncodedVideo } from "../../utilities/encodedVideoStorage/uploadEncodedVideo"; -import { findUserInCache } from "../../services/UserCache/findUserInCache"; -import { cacheUsers } from "../../services/UserCache/cacheUser"; -import { findAppUserProfileCache } from "../../services/AppUserProfileCache/findAppUserProfileCache"; -import { cacheAppUserProfile } from "../../services/AppUserProfileCache/cacheAppUserProfile"; - -/** - * Updates a post with new details, including handling image and video URL uploads and validating input fields. - * - * This function updates an existing post based on the provided input. It retrieves and validates the current user and their app profile, checks if the user has the necessary permissions, handles media file uploads, and performs input validation before updating the post in the database. The function returns the updated post after applying changes. - * - * @param _parent - This parameter represents the parent resolver in the GraphQL schema and is not used in this function. - * @param args - The arguments passed to the GraphQL mutation, including the post's `id` and data to update, such as `title`, `text`, `imageUrl`, and `videoUrl`. - * @param context - Provides contextual information, including the current user's ID. This is used to authenticate and authorize the request. - * - * @returns The updated post with all its fields. - */ -export const updatePost: MutationResolvers["updatePost"] = async ( - _parent, - args, - context, -) => { - let currentUser: InterfaceUser | null; - const userFoundInCache = await findUserInCache([context.userId]); - currentUser = userFoundInCache[0]; - if (currentUser === null) { - currentUser = await User.findOne({ - _id: context.userId, - }).lean(); - if (currentUser !== null) { - await cacheUsers([currentUser]); - } - } - - if (!currentUser) { - throw new errors.NotFoundError( - requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), - USER_NOT_FOUND_ERROR.CODE, - USER_NOT_FOUND_ERROR.PARAM, - ); - } - - let currentUserAppProfile: InterfaceAppUserProfile | null; - const appUserProfileFoundInCache = await findAppUserProfileCache([ - currentUser.appUserProfileId?.toString(), - ]); - currentUserAppProfile = appUserProfileFoundInCache[0]; - if (currentUserAppProfile === null) { - currentUserAppProfile = await AppUserProfile.findOne({ - userId: currentUser._id, - }).lean(); - if (currentUserAppProfile !== null) { - await cacheAppUserProfile([currentUserAppProfile]); - } - } - if (!currentUserAppProfile) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - let post: InterfacePost | null; - - const postFoundInCache = await findPostsInCache([args.id]); - - post = postFoundInCache[0]; - - if (postFoundInCache[0] === null) { - post = await Post.findOne({ - _id: args.id, - }).lean(); - if (post !== null) { - await cachePosts([post]); - } - } - - // Check if the post exists - if (!post) { - throw new errors.NotFoundError( - requestContext.translate(POST_NOT_FOUND_ERROR.MESSAGE), - POST_NOT_FOUND_ERROR.CODE, - POST_NOT_FOUND_ERROR.PARAM, - ); - } - - // Check if the user has the right to update the post - const currentUserIsPostCreator = post.creatorId.equals(context.userId); - const isSuperAdmin = currentUserAppProfile.isSuperAdmin; - const isAdminOfPostOrganization = currentUserAppProfile?.adminFor.some( - (orgID) => - orgID && new Types.ObjectId(orgID?.toString()).equals(post?.organization), - ); - - // checks if current user is an creator of the post with _id === args.id - if ( - !currentUserIsPostCreator && - !isAdminOfPostOrganization && - !isSuperAdmin - ) { - throw new errors.UnauthorizedError( - requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), - USER_NOT_AUTHORIZED_ERROR.CODE, - USER_NOT_AUTHORIZED_ERROR.PARAM, - ); - } - - // Handle image and video URL uploads - if (args.data?.imageUrl && args.data?.imageUrl !== null) { - args.data.imageUrl = await uploadEncodedImage( - args.data.imageUrl, - post.imageUrl, - ); - } - - if (args.data?.videoUrl && args.data?.videoUrl !== null) { - args.data.videoUrl = await uploadEncodedVideo( - args.data.videoUrl, - post.videoUrl, - ); - } - - // Validate title and pinned status - if (args.data?.title && !post.pinned) { - throw new errors.InputValidationError( - requestContext.translate(POST_NEEDS_TO_BE_PINNED.MESSAGE), - POST_NEEDS_TO_BE_PINNED.CODE, - ); - } else if (!args.data?.title && post.pinned) { - throw new errors.InputValidationError( - requestContext.translate(PLEASE_PROVIDE_TITLE.MESSAGE), - PLEASE_PROVIDE_TITLE.CODE, - ); - } - - // Validate input lengths - const validationResultTitle = isValidString(args.data?.title ?? "", 256); - const validationResultText = isValidString(args.data?.text ?? "", 500); - if (!validationResultTitle.isLessThanMaxLength) { - throw new errors.InputValidationError( - requestContext.translate( - `${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, - ), - LENGTH_VALIDATION_ERROR.CODE, - ); - } - if (!validationResultText.isLessThanMaxLength) { - throw new errors.InputValidationError( - requestContext.translate( - `${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, - ), - LENGTH_VALIDATION_ERROR.CODE, - ); - } - - // Update the post in the database - const updatedPost = await Post.findOneAndUpdate( - { - _id: args.id, - }, - { - ...(args.data as Record), - }, - { - new: true, - }, - ).lean(); - - if (updatedPost !== null) { - await cachePosts([updatedPost]); - } - - return updatedPost as InterfacePost; -}; diff --git a/src/resolvers/Mutation/updateSessionTimeout.ts b/src/resolvers/Mutation/updateSessionTimeout.ts new file mode 100644 index 0000000000..67fa92d536 --- /dev/null +++ b/src/resolvers/Mutation/updateSessionTimeout.ts @@ -0,0 +1,89 @@ +import type { InterfaceAppUserProfile } from "../../models"; +import { User, AppUserProfile } from "../../models"; +import { + COMMUNITY_NOT_FOUND_ERROR, + INVALID_TIMEOUT_RANGE, + USER_NOT_FOUND_ERROR, + APP_USER_PROFILE_NOT_FOUND_ERROR, + MINIMUM_TIMEOUT_MINUTES, + MAXIMUM_TIMEOUT_MINUTES, +} from "../../constants"; +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import { errors, requestContext } from "../../libraries"; +import { superAdminCheck } from "../../utilities"; +import { Community } from "../../models/Community"; + +/** + * This function updates the session timeout and can only be performed by superadmin users. + * @param _parent - parent of the current request + * @param args - payload provided with the request, including organizationId and timeout + * @param context - context of the entire application, containing user information + * @returns - A message true if the organization timeout is updated successfully + * @throws - NotFoundError: If the user, appuserprofile or organization is not found + * @throws - ValidationError: If the user is not an admin or superadmin, or if the timeout is outside the valid range + * @throws - InternalServerError: If there is an error updating the organization timeout + * + */ + +export const updateSessionTimeout: MutationResolvers["updateSessionTimeout"] = + async (_parent, args, context) => { + const userId = context.userId; + const user = await User.findById(userId).lean(); + + if (!user) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + + //const appuserprofile: InterfaceAppUserProfile | null = await AppUserProfile.findOne({userId: userId}).lean(); + const appuserprofile: InterfaceAppUserProfile | null = + await AppUserProfile.findById(user.appUserProfileId).lean(); //more appropriate since it shows the link between the user and the userprofile + + if (!appuserprofile) { + throw new errors.NotFoundError( + requestContext.translate(APP_USER_PROFILE_NOT_FOUND_ERROR.MESSAGE), + APP_USER_PROFILE_NOT_FOUND_ERROR.CODE, + APP_USER_PROFILE_NOT_FOUND_ERROR.PARAM, + ); + } + + superAdminCheck(appuserprofile); + + const community = await Community.findOne().lean(); + + if (!community) { + throw new errors.NotFoundError( + requestContext.translate(COMMUNITY_NOT_FOUND_ERROR.MESSAGE), + COMMUNITY_NOT_FOUND_ERROR.CODE, + COMMUNITY_NOT_FOUND_ERROR.PARAM, + ); + } + + if ( + args.timeout < MINIMUM_TIMEOUT_MINUTES || + args.timeout > MAXIMUM_TIMEOUT_MINUTES || + args.timeout % 5 !== 0 + ) { + throw new errors.ValidationError( + [ + { + message: requestContext.translate(INVALID_TIMEOUT_RANGE.MESSAGE), + code: INVALID_TIMEOUT_RANGE.CODE, + param: INVALID_TIMEOUT_RANGE.PARAM, + }, + ], + INVALID_TIMEOUT_RANGE.MESSAGE, + ); + } + + await Community.findByIdAndUpdate( + community._id, + { timeout: args.timeout }, + { new: true }, + ); + + return true; + }; diff --git a/src/resolvers/Mutation/updateUserProfile.ts b/src/resolvers/Mutation/updateUserProfile.ts index ee8c0e36ac..62c1e602e2 100644 --- a/src/resolvers/Mutation/updateUserProfile.ts +++ b/src/resolvers/Mutation/updateUserProfile.ts @@ -142,7 +142,7 @@ export const updateUserProfile: MutationResolvers["updateUserProfile"] = async ( }, ).lean(); if (updatedUser != null) { - await deleteUserFromCache(updatedUser?._id.toString() || ""); + await deleteUserFromCache(updatedUser?._id.toString()); await cacheUsers([updatedUser]); } @@ -159,11 +159,6 @@ export const updateUserProfile: MutationResolvers["updateUserProfile"] = async ( ); } - if (updatedUser != null) { - updatedUser.image = updatedUser?.image - ? `${context.apiRootUrl}${updatedUser?.image}` - : null; - } if (args.data == undefined) updatedUser = null; return updatedUser ?? ({} as InterfaceUser); diff --git a/src/resolvers/Mutation/updateVolunteerMembership.ts b/src/resolvers/Mutation/updateVolunteerMembership.ts new file mode 100644 index 0000000000..18d28e483d --- /dev/null +++ b/src/resolvers/Mutation/updateVolunteerMembership.ts @@ -0,0 +1,137 @@ +import type { MutationResolvers } from "../../types/generatedGraphQLTypes"; +import type { + InterfaceEvent, + InterfaceEventVolunteerGroup, + InterfaceVolunteerMembership, +} from "../../models"; +import { + Event, + EventVolunteer, + EventVolunteerGroup, + VolunteerMembership, +} from "../../models"; +import { + checkUserExists, + checkVolunteerMembershipExists, +} from "../../utilities/checks"; +import { adminCheck } from "../../utilities"; +import { errors, requestContext } from "../../libraries"; +import { USER_NOT_AUTHORIZED_ERROR } from "../../constants"; + +/** + * Helper function to handle updates when status is accepted + */ +const handleAcceptedStatusUpdates = async ( + membership: InterfaceVolunteerMembership, +): Promise => { + const updatePromises = []; + + // Always update EventVolunteer to set hasAccepted to true + updatePromises.push( + EventVolunteer.findOneAndUpdate( + { _id: membership.volunteer, event: membership.event }, + { + $set: { hasAccepted: true }, + ...(membership.group && { $push: { groups: membership.group } }), + }, + ), + ); + + // Always update Event to add volunteer + updatePromises.push( + Event.findOneAndUpdate( + { _id: membership.event }, + { $addToSet: { volunteers: membership.volunteer } }, + ), + ); + + // If group exists, update the EventVolunteerGroup as well + if (membership.group) { + updatePromises.push( + EventVolunteerGroup.findOneAndUpdate( + { _id: membership.group }, + { $addToSet: { volunteers: membership.volunteer } }, + ), + ); + } + + // Execute all updates in parallel + await Promise.all(updatePromises); +}; + +/** + * This function enables to update an Volunteer Membership + * @param _parent - parent of current request + * @param args - payload provided with the request + * @param context - context of entire application + * @remarks The following checks are done: + * 1. Whether the user exists + * 2. Update the Volunteer Membership + * 3. update related fields of Volunteer Group & Volunteer + */ +export const updateVolunteerMembership: MutationResolvers["updateVolunteerMembership"] = + async (_parent, args, context) => { + const currentUser = await checkUserExists(context.userId); + const volunteerMembership = await checkVolunteerMembershipExists(args.id); + + const event = (await Event.findById(volunteerMembership.event) + .populate("organization") + .lean()) as InterfaceEvent; + + if (volunteerMembership.status != "invited") { + // Check if the user is authorized to update the volunteer membership + const isAdminOrSuperAdmin = await adminCheck( + currentUser._id, + event.organization, + false, + ); + const isEventAdmin = event.admins.some( + (admin) => admin.toString() == currentUser._id.toString(), + ); + let isGroupLeader = false; + if (volunteerMembership.group != undefined) { + // check if current user is group leader + const group = (await EventVolunteerGroup.findById( + volunteerMembership.group, + ).lean()) as InterfaceEventVolunteerGroup; + isGroupLeader = group.leader.toString() == currentUser._id.toString(); + } + + // If the user is not an admin or super admin, event admin, or group leader, throw an error + if (!isAdminOrSuperAdmin && !isEventAdmin && !isGroupLeader) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + } + + const updatedVolunteerMembership = + (await VolunteerMembership.findOneAndUpdate( + { + _id: args.id, + }, + { + $set: { + status: args.status as + | "invited" + | "requested" + | "accepted" + | "rejected", + updatedBy: context.userId, + }, + }, + { + new: true, + runValidators: true, + }, + ).lean()) as InterfaceVolunteerMembership; + + // Handle additional updates if the status is accepted + if (args.status === "accepted") { + await handleAcceptedStatusUpdates(updatedVolunteerMembership); + } + + return updatedVolunteerMembership; + }; diff --git a/src/resolvers/Organization/image.ts b/src/resolvers/Organization/image.ts index b94afa9975..fed5e163b6 100644 --- a/src/resolvers/Organization/image.ts +++ b/src/resolvers/Organization/image.ts @@ -12,13 +12,9 @@ import type { OrganizationResolvers } from "../../types/generatedGraphQLTypes"; * @see OrganizationResolvers - The type definition for the resolvers of the Organization fields. * */ -export const image: OrganizationResolvers["image"] = ( - parent, - _args, - context, -) => { +export const image: OrganizationResolvers["image"] = (parent) => { if (parent.image) { - return `${context.apiRootUrl}${parent.image}`; + return parent.image; } return null; }; diff --git a/src/resolvers/Organization/posts.ts b/src/resolvers/Organization/posts.ts index 7aadc5f786..9f3b37334f 100644 --- a/src/resolvers/Organization/posts.ts +++ b/src/resolvers/Organization/posts.ts @@ -36,11 +36,7 @@ import { MAXIMUM_FETCH_LIMIT } from "../../constants"; * @see OrganizationResolvers - The type definition for the resolvers of the Organization fields. * */ -export const posts: OrganizationResolvers["posts"] = async ( - parent, - args, - context, -) => { +export const posts: OrganizationResolvers["posts"] = async (parent, args) => { const parseGraphQLConnectionArgumentsResult = await parseGraphQLConnectionArguments({ args, @@ -79,10 +75,13 @@ export const posts: OrganizationResolvers["posts"] = async ( }) .sort(sort) .limit(parsedArgs.limit) - .populate({ - path: "likedBy", - select: "image firstName lastName", - }) + .populate([ + { + path: "likedBy", + select: "image firstName lastName", + }, + { path: "file" }, + ]) .lean() .exec(), @@ -92,21 +91,12 @@ export const posts: OrganizationResolvers["posts"] = async ( .countDocuments() .exec(), ]); - const posts = objectList.map((post: InterfacePost) => ({ - ...post, - imageUrl: post.imageUrl - ? new URL(post.imageUrl, context.apiRootUrl).toString() - : null, - videoUrl: post.videoUrl - ? new URL(post.videoUrl, context.apiRootUrl).toString() - : null, - })); return transformToDefaultGraphQLConnection< ParsedCursor, InterfacePost, InterfacePost >({ - objectList: posts, + objectList, parsedArgs, totalCount, }); diff --git a/src/resolvers/Organization/userTags.ts b/src/resolvers/Organization/userTags.ts index 2b4160cf36..c82cceaef7 100644 --- a/src/resolvers/Organization/userTags.ts +++ b/src/resolvers/Organization/userTags.ts @@ -2,9 +2,7 @@ import type { OrganizationResolvers } from "../../types/generatedGraphQLTypes"; import type { InterfaceOrganizationTagUser } from "../../models"; import { OrganizationTagUser } from "../../models"; import { - getCommonGraphQLConnectionFilter, - getCommonGraphQLConnectionSort, - parseGraphQLConnectionArguments, + parseGraphQLConnectionArgumentsWithSortedByAndWhere, transformToDefaultGraphQLConnection, type DefaultGraphQLArgumentError, type ParseGraphQLConnectionCursorArguments, @@ -13,6 +11,12 @@ import { import { GraphQLError } from "graphql"; import { MAXIMUM_FETCH_LIMIT } from "../../constants"; import type { Types } from "mongoose"; +import { + getUserTagGraphQLConnectionFilter, + getUserTagGraphQLConnectionSort, + parseUserTagSortedBy, + parseUserTagWhere, +} from "../../utilities/userTagsPaginationUtils"; /** * Resolver function for the `userTags` field of an `Organization`. @@ -37,14 +41,20 @@ export const userTags: OrganizationResolvers["userTags"] = async ( parent, args, ) => { + const parseWhereResult = parseUserTagWhere(args.where); + const parseSortedByResult = parseUserTagSortedBy(args.sortedBy); + const parseGraphQLConnectionArgumentsResult = - await parseGraphQLConnectionArguments({ + await parseGraphQLConnectionArgumentsWithSortedByAndWhere({ args, - parseCursor: (args) => + parseSortedByResult, + parseWhereResult, + parseCursor: /* c8 ignore start */ (args) => parseCursor({ ...args, organizationId: parent._id, }), + /* c8 ignore stop */ maximumLimit: MAXIMUM_FETCH_LIMIT, }); @@ -59,26 +69,43 @@ export const userTags: OrganizationResolvers["userTags"] = async ( const { parsedArgs } = parseGraphQLConnectionArgumentsResult; - const filter = getCommonGraphQLConnectionFilter({ + const objectListFilter = getUserTagGraphQLConnectionFilter({ cursor: parsedArgs.cursor, direction: parsedArgs.direction, + sortById: parsedArgs.sort.sortById, + nameStartsWith: parsedArgs.filter.nameStartsWith, }); - const sort = getCommonGraphQLConnectionSort({ + // don't use _id as a filter in while counting the documents + // _id is only used for pagination + const totalCountFilter = Object.fromEntries( + Object.entries(objectListFilter).filter(([key]) => key !== "_id"), + ); + + const sort = getUserTagGraphQLConnectionSort({ direction: parsedArgs.direction, + sortById: parsedArgs.sort.sortById, }); + // if there's no search input, we'll list all the root tag + // otherwise we'll also list the subtags matching the filter + const parentTagIdFilter = parsedArgs.filter.nameStartsWith + ? {} + : { parentTagId: null }; + const [objectList, totalCount] = await Promise.all([ OrganizationTagUser.find({ - ...filter, + ...objectListFilter, + ...parentTagIdFilter, organizationId: parent._id, - parentTagId: null, }) .sort(sort) .limit(parsedArgs.limit) .lean() .exec(), OrganizationTagUser.find({ + ...totalCountFilter, + ...parentTagIdFilter, organizationId: parent._id, }) .countDocuments() diff --git a/src/resolvers/Query/actionItemsByOrganization.ts b/src/resolvers/Query/actionItemsByOrganization.ts index 828cf58005..ac7b10f7cd 100644 --- a/src/resolvers/Query/actionItemsByOrganization.ts +++ b/src/resolvers/Query/actionItemsByOrganization.ts @@ -2,6 +2,7 @@ import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; import type { InterfaceActionItem, InterfaceActionItemCategory, + InterfaceEventVolunteer, InterfaceUser, } from "../../models"; import { ActionItem } from "../../models"; @@ -24,7 +25,14 @@ export const actionItemsByOrganization: QueryResolvers["actionItemsByOrganizatio ...where, }) .populate("creator") - .populate("assignee") + .populate({ + path: "assignee", + populate: { + path: "user", + }, + }) + .populate("assigneeUser") + .populate("assigneeGroup") .populate("assigner") .populate("actionItemCategory") .populate("organization") @@ -46,10 +54,24 @@ export const actionItemsByOrganization: QueryResolvers["actionItemsByOrganizatio // Filter the action items based on assignee name if (args.where?.assigneeName) { + const assigneeName = args.where.assigneeName.toLowerCase(); filteredActionItems = filteredActionItems.filter((item) => { - const tempItem = item as InterfaceActionItem; - const assignee = tempItem.assignee as InterfaceUser; - return assignee.firstName.includes(args?.where?.assigneeName as string); + const assigneeType = item.assigneeType; + + if (assigneeType === "EventVolunteer") { + const assignee = item.assignee as InterfaceEventVolunteer; + const assigneeUser = assignee.user as InterfaceUser; + const name = + `${assigneeUser.firstName} ${assigneeUser.lastName}`.toLowerCase(); + + return name.includes(assigneeName); + } else if (assigneeType === "EventVolunteerGroup") { + return item.assigneeGroup.name.toLowerCase().includes(assigneeName); + } else if (assigneeType === "User") { + const name = + `${item.assigneeUser.firstName} ${item.assigneeUser.lastName}`.toLowerCase(); + return name.includes(assigneeName); + } }); } diff --git a/src/resolvers/Query/actionItemsByUser.ts b/src/resolvers/Query/actionItemsByUser.ts new file mode 100644 index 0000000000..43f1af3b76 --- /dev/null +++ b/src/resolvers/Query/actionItemsByUser.ts @@ -0,0 +1,109 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import type { + InterfaceActionItem, + InterfaceActionItemCategory, + InterfaceEvent, + InterfaceEventVolunteer, + InterfaceUser, +} from "../../models"; +import { ActionItem, EventVolunteer } from "../../models"; + +/** + * This query will fetch all action items for an organization from database. + * @param _parent- + * @param args - An object that contains `organizationId` which is the _id of the Organization. + * @returns An `actionItems` object that holds all action items for the Event. + */ +export const actionItemsByUser: QueryResolvers["actionItemsByUser"] = async ( + _parent, + args, +) => { + const volunteerObjects = await EventVolunteer.find({ + user: args.userId, + }) + .populate({ + path: "assignments", + populate: [ + { path: "creator" }, + { + path: "assignee", + populate: { path: "user" }, + }, + { path: "assigneeGroup" }, + { path: "assigner" }, + { path: "actionItemCategory" }, + { path: "organization" }, + { path: "event" }, + ], + }) + .populate("event") + .lean(); + + const userActionItems = await ActionItem.find({ + assigneeType: "User", + assigneeUser: args.userId, + organization: args.where?.orgId, + }) + .populate("creator") + .populate("assigner") + .populate("actionItemCategory") + .populate("organization") + .populate("assigneeUser") + .lean(); + + const actionItems: InterfaceActionItem[] = []; + volunteerObjects.forEach((volunteer) => { + const tempEvent = volunteer.event as InterfaceEvent; + if (tempEvent.organization._id.toString() === args.where?.orgId) + actionItems.push(...volunteer.assignments); + }); + + actionItems.push(...userActionItems); + + let filteredActionItems: InterfaceActionItem[] = actionItems; + + // filtering based on category name + if (args.where?.categoryName) { + const categoryName = args.where.categoryName.toLowerCase(); + filteredActionItems = filteredActionItems.filter((item) => { + const category = item.actionItemCategory as InterfaceActionItemCategory; + return category.name.toLowerCase().includes(categoryName); + }); + } + + // filtering based on assignee name + if (args.where?.assigneeName) { + const assigneeName = args.where.assigneeName.toLowerCase(); + + filteredActionItems = filteredActionItems.filter((item) => { + const assigneeType = item.assigneeType; + + if (assigneeType === "EventVolunteer") { + const assignee = item.assignee as InterfaceEventVolunteer; + const assigneeUser = assignee.user as InterfaceUser; + const name = + `${assigneeUser.firstName} ${assigneeUser.lastName}`.toLowerCase(); + + return name.includes(assigneeName); + } else if (assigneeType === "EventVolunteerGroup") { + return item.assigneeGroup.name.toLowerCase().includes(assigneeName); + } else if (assigneeType === "User") { + const name = + `${item.assigneeUser.firstName} ${item.assigneeUser.lastName}`.toLowerCase(); + return name.includes(assigneeName); + } + }); + } + + if (args.orderBy === "dueDate_DESC") { + filteredActionItems.sort((a, b) => { + return new Date(b.dueDate).getTime() - new Date(a.dueDate).getTime(); + }); + } else if (args.orderBy === "dueDate_ASC") { + filteredActionItems.sort((a, b) => { + return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime(); + }); + } + + return filteredActionItems as InterfaceActionItem[]; +}; diff --git a/src/resolvers/Query/chatById.ts b/src/resolvers/Query/chatById.ts new file mode 100644 index 0000000000..81fe769977 --- /dev/null +++ b/src/resolvers/Query/chatById.ts @@ -0,0 +1,26 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import { errors } from "../../libraries"; +import { Chat } from "../../models"; +import { CHAT_NOT_FOUND_ERROR } from "../../constants"; +/** + * This query will fetch Chats by a specified id from the database. + * @param _parent- + * @param args - An object that contains `id` of the user. + * @returns An object `Chat`. + * If the `Chat` object is null then it throws `NotFoundError` error. + * @remarks You can learn about GraphQL `Resolvers` + * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. + */ +export const chatById: QueryResolvers["chatById"] = async (_parent, args) => { + const chat = await Chat.findById(args.id).lean(); + + if (!chat) { + throw new errors.NotFoundError( + CHAT_NOT_FOUND_ERROR.DESC, + CHAT_NOT_FOUND_ERROR.CODE, + CHAT_NOT_FOUND_ERROR.PARAM, + ); + } + + return chat; +}; diff --git a/src/resolvers/Query/chatsByUserId.ts b/src/resolvers/Query/chatsByUserId.ts new file mode 100644 index 0000000000..c99904ab9a --- /dev/null +++ b/src/resolvers/Query/chatsByUserId.ts @@ -0,0 +1,21 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; +/** + * This query will fetch all the Chats for the current user from the database. + * @param _parent- + * @param args - An object that contains `id` of the user. + * @returns An object `chats` that contains all chats of the current user. + * If the `Chats` object is null then returns an empty array. + * @remarks You can learn about GraphQL `Resolvers` + * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. + */ +export const chatsByUserId: QueryResolvers["chatsByUserId"] = async ( + _parent, + args, +) => { + const chats = await Chat.find({ + users: args.id, + }).lean(); + + return chats || []; +}; diff --git a/src/resolvers/Query/checkAuth.ts b/src/resolvers/Query/checkAuth.ts index 09a0c6a7de..1254fdeb59 100644 --- a/src/resolvers/Query/checkAuth.ts +++ b/src/resolvers/Query/checkAuth.ts @@ -37,11 +37,5 @@ export const checkAuth: QueryResolvers["checkAuth"] = async ( ); } - return { - ...currentUser, - image: currentUser.image - ? `${context.apiRootUrl}${currentUser.image}` - : null, - organizationsBlockedBy: [], - }; + return currentUser; }; diff --git a/src/resolvers/Query/directChatById.ts b/src/resolvers/Query/directChatById.ts deleted file mode 100644 index 00a4b9f852..0000000000 --- a/src/resolvers/Query/directChatById.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { DirectChat } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * This query will fetch all messages for a certain direct chat for the user from database. - * @param _parent- - * @param args - An object that contains `id` of the direct chat. - * @returns A `directChatsMessages` object that holds all of the messages from the specified direct chat. - * If the `directChatsMessages` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ - -export const directChatById: QueryResolvers["directChatById"] = async ( - _parent, - args, -) => { - const directChat = await DirectChat.findById(args.id).lean(); - - if (!directChat) { - throw new errors.NotFoundError( - CHAT_NOT_FOUND_ERROR.DESC, - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - return directChat; -}; diff --git a/src/resolvers/Query/directChatsByUserID.ts b/src/resolvers/Query/directChatsByUserID.ts deleted file mode 100644 index efb34e93dd..0000000000 --- a/src/resolvers/Query/directChatsByUserID.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { DirectChat } from "../../models"; -/** - * This query will fetch all the Direct chats for the current user from the database. - * @param _parent- - * @param args - An object that contains `id` of the user. - * @returns An object `directChats` that contains all direct chats of the current user. - * If the `directChats` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ -export const directChatsByUserID: QueryResolvers["directChatsByUserID"] = - async (_parent, args) => { - const directChats = await DirectChat.find({ - users: args.id, - }).lean(); - - if (directChats.length === 0) { - throw new errors.NotFoundError( - "DirectChats not found", - "directChats.notFound", - "directChats", - ); - } - - return directChats; - }; diff --git a/src/resolvers/Query/directChatsMessagesByChatID.ts b/src/resolvers/Query/directChatsMessagesByChatID.ts deleted file mode 100644 index 173eada6e5..0000000000 --- a/src/resolvers/Query/directChatsMessagesByChatID.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { DirectChatMessage } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * This query will fetch all messages for a certain direct chat for the user from database. - * @param _parent- - * @param args - An object that contains `id` of the direct chat. - * @returns A `directChatsMessages` object that holds all of the messages from the specified direct chat. - * If the `directChatsMessages` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ - -export const directChatsMessagesByChatID: QueryResolvers["directChatsMessagesByChatID"] = - async (_parent, args) => { - const directChatsMessages = await DirectChatMessage.find({ - directChatMessageBelongsTo: args.id, - }).lean(); - - if (directChatsMessages.length === 0) { - throw new errors.NotFoundError( - CHAT_NOT_FOUND_ERROR.DESC, - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - return directChatsMessages; - }; diff --git a/src/resolvers/Query/eventVolunteersByEvent.ts b/src/resolvers/Query/eventVolunteersByEvent.ts deleted file mode 100644 index e982f58e18..0000000000 --- a/src/resolvers/Query/eventVolunteersByEvent.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { EventVolunteer } from "../../models"; -/** - * This query will fetch all events volunteers for the given eventId from database. - * @param _parent- - * @param args - An object that contains `id` of the Event. - * @returns An object that holds all Event Volunteers for the given Event - */ -export const eventVolunteersByEvent: QueryResolvers["eventVolunteersByEvent"] = - async (_parent, args) => { - const eventId = args.id; - - const volunteers = EventVolunteer.find({ - eventId: eventId, - }) - .populate("userId", "-password") - .lean(); - - return volunteers; - }; diff --git a/src/resolvers/Query/eventsAttendedByUser.ts b/src/resolvers/Query/eventsAttendedByUser.ts new file mode 100644 index 0000000000..202a962707 --- /dev/null +++ b/src/resolvers/Query/eventsAttendedByUser.ts @@ -0,0 +1,28 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import { Event } from "../../models"; +import { getSort } from "./helperFunctions/getSort"; + +/** + * This query will fetch all the events for which user attended from the database. + * @param _parent- + * @param args - An object that contains `id` of the user and `orderBy`. + * @returns An object that contains the Event data. + * @remarks The query function uses `getSort()` function to sort the data in specified. + */ +export const eventsAttendedByUser: QueryResolvers["eventsAttendedByUser"] = + async (_parent, args) => { + const sort = getSort(args.orderBy); + + return await Event.find({ + registrants: { + $elemMatch: { + userId: args.id, + status: "ACTIVE", + }, + }, + }) + .sort(sort) + .populate("creatorId", "-password") + .populate("admins", "-password") + .lean(); + }; diff --git a/src/resolvers/Query/eventsByOrganizationConnection.ts b/src/resolvers/Query/eventsByOrganizationConnection.ts index e184a2bc47..0991d0a8af 100644 --- a/src/resolvers/Query/eventsByOrganizationConnection.ts +++ b/src/resolvers/Query/eventsByOrganizationConnection.ts @@ -4,6 +4,7 @@ import { Event } from "../../models"; import { getSort } from "./helperFunctions/getSort"; import { getWhere } from "./helperFunctions/getWhere"; import { createRecurringEventInstancesDuringQuery } from "../../helpers/event/createEventHelpers"; + /** * Retrieves events for a specific organization based on the provided query parameters. * @@ -26,10 +27,19 @@ export const eventsByOrganizationConnection: QueryResolvers["eventsByOrganizatio // get the where and sort let where = getWhere(args.where); const sort = getSort(args.orderBy); - + const currentDate = new Date(); where = { ...where, isBaseRecurringEvent: false, + ...(args.upcomingOnly && { + $or: [ + { endDate: { $gt: currentDate } }, // Future dates + { + endDate: { $eq: currentDate.toISOString().split("T")[0] }, // Events today + endTime: { $gt: currentDate }, // But start time is after current time + }, + ], + }), }; // find all the events according to the requirements @@ -39,6 +49,13 @@ export const eventsByOrganizationConnection: QueryResolvers["eventsByOrganizatio .skip(args.skip ?? 0) .populate("creatorId", "-password") .populate("admins", "-password") + .populate("volunteerGroups") + .populate({ + path: "volunteers", + populate: { + path: "user", + }, + }) .lean(); return events; diff --git a/src/resolvers/Query/getEventVolunteerGroups.ts b/src/resolvers/Query/getEventVolunteerGroups.ts index bb5e7d558e..f4f6913d3e 100644 --- a/src/resolvers/Query/getEventVolunteerGroups.ts +++ b/src/resolvers/Query/getEventVolunteerGroups.ts @@ -1,4 +1,10 @@ -import { EventVolunteerGroup } from "../../models"; +import type { + InterfaceEvent, + InterfaceEventVolunteer, + InterfaceEventVolunteerGroup, + InterfaceUser, +} from "../../models"; +import { EventVolunteer, EventVolunteerGroup } from "../../models"; import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; import { getWhere } from "./helperFunctions/getWhere"; /** @@ -9,14 +15,111 @@ import { getWhere } from "./helperFunctions/getWhere"; */ export const getEventVolunteerGroups: QueryResolvers["getEventVolunteerGroups"] = async (_parent, args) => { - const where = getWhere(args.where); - const eventVolunteerGroups = await EventVolunteerGroup.find({ - ...where, - }) - .populate("eventId") - .populate("creatorId") - .populate("leaderId") - .populate("volunteers"); + const { eventId, leaderName, userId, orgId } = args.where; + let eventVolunteerGroups: InterfaceEventVolunteerGroup[] = []; + if (eventId) { + const where = getWhere({ name_contains: args.where.name_contains }); + eventVolunteerGroups = await EventVolunteerGroup.find({ + event: eventId, + ...where, + }) + .populate("event") + .populate("creator") + .populate("leader") + .populate({ + path: "volunteers", + populate: { + path: "user", + }, + }) + .populate({ + path: "assignments", + populate: { + path: "actionItemCategory", + }, + }) + .lean(); + } else if (userId && orgId) { + const volunteerProfiles = (await EventVolunteer.find({ + user: userId, + }) + .populate({ + path: "groups", + populate: [ + { + path: "event", + }, + { + path: "creator", + }, + { + path: "leader", + }, + { + path: "volunteers", + populate: { + path: "user", + }, + }, + { + path: "assignments", + populate: { + path: "actionItemCategory", + }, + }, + ], + }) + .populate("event") + .lean()) as InterfaceEventVolunteer[]; + volunteerProfiles.forEach((volunteer) => { + const tempEvent = volunteer.event as InterfaceEvent; + if (tempEvent.organization.toString() == orgId) + eventVolunteerGroups.push(...volunteer.groups); + }); + } - return eventVolunteerGroups; + let filteredEventVolunteerGroups: InterfaceEventVolunteerGroup[] = + eventVolunteerGroups; + + if (leaderName) { + const tempName = leaderName.toLowerCase(); + filteredEventVolunteerGroups = filteredEventVolunteerGroups.filter( + (group) => { + const tempGroup = group as InterfaceEventVolunteerGroup; + const tempLeader = tempGroup.leader as InterfaceUser; + const { firstName, lastName } = tempLeader; + const name = `${firstName} ${lastName}`.toLowerCase(); + return name.includes(tempName); + }, + ); + } + + const sortConfigs = { + /* c8 ignore start */ + volunteers_ASC: ( + a: InterfaceEventVolunteerGroup, + b: InterfaceEventVolunteerGroup, + ): number => a.volunteers.length - b.volunteers.length, + /* c8 ignore stop */ + volunteers_DESC: ( + a: InterfaceEventVolunteerGroup, + b: InterfaceEventVolunteerGroup, + ): number => b.volunteers.length - a.volunteers.length, + assignments_ASC: ( + a: InterfaceEventVolunteerGroup, + b: InterfaceEventVolunteerGroup, + ): number => a.assignments.length - b.assignments.length, + assignments_DESC: ( + a: InterfaceEventVolunteerGroup, + b: InterfaceEventVolunteerGroup, + ): number => b.assignments.length - a.assignments.length, + }; + + if (args.orderBy && args.orderBy in sortConfigs) { + filteredEventVolunteerGroups.sort( + sortConfigs[args.orderBy as keyof typeof sortConfigs], + ); + } + + return filteredEventVolunteerGroups; }; diff --git a/src/resolvers/Query/getEventVolunteers.ts b/src/resolvers/Query/getEventVolunteers.ts new file mode 100644 index 0000000000..ccb461f70c --- /dev/null +++ b/src/resolvers/Query/getEventVolunteers.ts @@ -0,0 +1,61 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import type { InterfaceEventVolunteer, InterfaceUser } from "../../models"; +import { EventVolunteer } from "../../models"; +import { getSort } from "./helperFunctions/getSort"; +import { getWhere } from "./helperFunctions/getWhere"; + +/** + * This query will fetch all events volunteers for the given eventId from database. + * @param _parent- + * @param args - An object that contains `id` of the Event. + * @returns An object that holds all Event Volunteers for the given Event + */ +export const getEventVolunteers: QueryResolvers["getEventVolunteers"] = async ( + _parent, + args, +) => { + const sort = getSort(args.orderBy); + const { + id, + name_contains: nameContains, + hasAccepted, + eventId, + groupId, + } = args.where; + const where = getWhere({ id, hasAccepted }); + + const volunteers = await EventVolunteer.find({ + event: eventId, + ...(groupId && { + groups: { + $in: groupId, + }, + }), + ...where, + }) + .populate("user", "-password") + .populate("event") + .populate("groups") + .populate({ + path: "assignments", + populate: { + path: "actionItemCategory", + }, + }) + .sort(sort) + .lean(); + + let filteredVolunteers: InterfaceEventVolunteer[] = volunteers; + + if (nameContains) { + filteredVolunteers = filteredVolunteers.filter((volunteer) => { + const tempVolunteer = volunteer as InterfaceEventVolunteer; + const tempUser = tempVolunteer.user as InterfaceUser; + const { firstName, lastName } = tempUser; + const name = `${firstName} ${lastName}`.toLowerCase(); + return name.includes(nameContains.toLowerCase()); + }); + } + + return filteredVolunteers; +}; diff --git a/src/resolvers/Query/getRecurringEvents.ts b/src/resolvers/Query/getRecurringEvents.ts new file mode 100644 index 0000000000..e36ad7bb77 --- /dev/null +++ b/src/resolvers/Query/getRecurringEvents.ts @@ -0,0 +1,25 @@ +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import { Event } from "../../models"; +import type { InterfaceEvent } from "../../models/Event"; +/** + * This query will fetch all the events with the same BaseRecurringEventId from the database. + * @param _parent - + * @param args - An object that contains `baseRecurringEventId` of the base recurring event. + * @returns An array of `Event` objects that are instances of the base recurring event. + */ + +export const getRecurringEvents: QueryResolvers["getRecurringEvents"] = async ( + _parent, + args, +) => { + try { + const recurringEvents = await Event.find({ + baseRecurringEventId: args.baseRecurringEventId, + }).lean(); + + return recurringEvents as InterfaceEvent[]; + } catch (error) { + console.error("Error fetching recurring events:", error); + throw error; + } +}; diff --git a/src/resolvers/Query/getUserTagAncestors.ts b/src/resolvers/Query/getUserTagAncestors.ts deleted file mode 100644 index cf516eb43e..0000000000 --- a/src/resolvers/Query/getUserTagAncestors.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { InterfaceOrganizationTagUser } from "../../models"; -import { OrganizationTagUser } from "../../models"; -import { errors, requestContext } from "../../libraries"; -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { TAG_NOT_FOUND } from "../../constants"; - -/** - * Retrieves the ancestor tags of a given user tag. - * - * This function fetches the ancestor tags of a specific user tag from the database. If the user tag - * is not found, it throws an error indicating that the item does not exist. - * - * @param _parent - This parameter is not used in this resolver function. - * @param args - The arguments provided by the GraphQL query, including the ID of the given user tag. - * - * @returns The ancestor tags of the user tag. - */ - -export const getUserTagAncestors: QueryResolvers["getUserTagAncestors"] = - async (_parent, args) => { - let currentTag = await OrganizationTagUser.findById(args.id).lean(); - - if (!currentTag) { - throw new errors.NotFoundError( - requestContext.translate(TAG_NOT_FOUND.MESSAGE), - TAG_NOT_FOUND.CODE, - TAG_NOT_FOUND.PARAM, - ); - } - - const tagAncestors = [currentTag]; - - while (currentTag?.parentTagId) { - const currentParent = (await OrganizationTagUser.findById( - currentTag.parentTagId, - ).lean()) as InterfaceOrganizationTagUser | null; - - if (currentParent) { - tagAncestors.push(currentParent); - currentTag = currentParent; - } - } - - return tagAncestors.reverse(); - }; diff --git a/src/resolvers/Query/getVolunteerMembership.ts b/src/resolvers/Query/getVolunteerMembership.ts new file mode 100644 index 0000000000..f9dc8f1831 --- /dev/null +++ b/src/resolvers/Query/getVolunteerMembership.ts @@ -0,0 +1,129 @@ +import type { + InputMaybe, + QueryResolvers, + VolunteerMembershipOrderByInput, +} from "../../types/generatedGraphQLTypes"; +import type { InterfaceVolunteerMembership } from "../../models"; +import { EventVolunteer, VolunteerMembership } from "../../models"; +import { getSort } from "./helperFunctions/getSort"; + +/** + * Helper function to fetch volunteer memberships by userId + */ +const getVolunteerMembershipsByUserId = async ( + userId: string, + orderBy: InputMaybe | undefined, + status?: string, +): Promise => { + const sort = getSort(orderBy); + const volunteerInstance = await EventVolunteer.find({ user: userId }).lean(); + const volunteerIds = volunteerInstance.map((volunteer) => volunteer._id); + + return await VolunteerMembership.find({ + volunteer: { $in: volunteerIds }, + ...(status && { status }), + }) + .sort(sort) + .populate("event") + .populate("group") + .populate({ + path: "volunteer", + populate: { + path: "user", + }, + }) + .lean(); +}; + +/** + * Helper function to fetch volunteer memberships by eventId + */ +const getVolunteerMembershipsByEventId = async ( + eventId: string, + orderBy: InputMaybe | undefined, + status?: string, + group?: string, +): Promise => { + const sort = getSort(orderBy); + + return await VolunteerMembership.find({ + event: eventId, + ...(status && { status }), + ...(group && { group: group }), + }) + .sort(sort) + .populate("event") + .populate("group") + .populate({ + path: "volunteer", + populate: { + path: "user", + }, + }) + .lean(); +}; + +/** + * Helper function to filter memberships based on various criteria + */ +const filterMemberships = ( + memberships: InterfaceVolunteerMembership[], + filter?: string, + eventTitle?: string, + userName?: string, +): InterfaceVolunteerMembership[] => { + return memberships.filter((membership) => { + const filterCondition = filter + ? filter === "group" + ? !!membership.group + : !membership.group + : true; + + const eventTitleCondition = eventTitle + ? membership.event.title.includes(eventTitle) + : true; + + const userNameCondition = userName + ? ( + membership.volunteer.user.firstName + + membership.volunteer.user.lastName + ).includes(userName) + : true; + + return filterCondition && eventTitleCondition && userNameCondition; + }); +}; + +export const getVolunteerMembership: QueryResolvers["getVolunteerMembership"] = + async (_parent, args) => { + const { status, userId, filter, eventTitle, eventId, userName, groupId } = + args.where; + + let volunteerMemberships: InterfaceVolunteerMembership[] = []; + + if (userId) { + volunteerMemberships = await getVolunteerMembershipsByUserId( + userId, + args.orderBy, + status ?? undefined, + ); + } else if (eventId) { + volunteerMemberships = await getVolunteerMembershipsByEventId( + eventId, + args.orderBy, + status ?? undefined, + groupId ?? undefined, + ); + } + + if (filter || eventTitle || userName) { + return filterMemberships( + volunteerMemberships, + filter ?? undefined, + eventTitle ?? undefined, + userName ?? undefined, + ); + } + + return volunteerMemberships; + }; diff --git a/src/resolvers/Query/getVolunteerRanks.ts b/src/resolvers/Query/getVolunteerRanks.ts new file mode 100644 index 0000000000..a117652f62 --- /dev/null +++ b/src/resolvers/Query/getVolunteerRanks.ts @@ -0,0 +1,146 @@ +import { startOfWeek, startOfMonth, startOfYear, endOfDay } from "date-fns"; +import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; +import type { InterfaceEvent, InterfaceUser } from "../../models"; +import { Event, EventVolunteer } from "../../models"; + +/** + * This query will fetch volunteer ranks based on the provided time frame (allTime, weekly, monthly, yearly), + * and it will filter the results based on an array of volunteer IDs. + * @param _parent - parent of the current request + * @param args - An object that contains where object for volunteer ranks. + * + * @returns An array of `VolunteerRank` object. + */ +export const getVolunteerRanks: QueryResolvers["getVolunteerRanks"] = async ( + _parent, + args, +) => { + const { orgId } = args; + const { timeFrame, orderBy, nameContains, limit } = args.where; + + const volunteerIds: string[] = []; + const events = (await Event.find({ + organization: orgId, + }).lean()) as InterfaceEvent[]; + + // Get all volunteer IDs from the events + events.forEach((event) => { + volunteerIds.push( + ...event.volunteers.map((volunteer) => volunteer.toString()), + ); + }); + + // Fetch all volunteers + const volunteers = await EventVolunteer.find({ + _id: { $in: volunteerIds }, + }) + .populate("user") + .lean(); + + const now = new Date(); + let startDate: Date | null = null; + let endDate: Date | null = null; + + // Determine the date range based on the timeframe + switch (timeFrame) { + case "weekly": + startDate = startOfWeek(now); + endDate = endOfDay(now); + break; + case "monthly": + startDate = startOfMonth(now); + endDate = endOfDay(now); + break; + case "yearly": + startDate = startOfYear(now); + endDate = endOfDay(now); + break; + case "allTime": + default: + startDate = null; // No filtering for "allTime" + endDate = null; + break; + } + + // Accumulate total hours per user + const userHoursMap = new Map< + string, + { hoursVolunteered: number; user: InterfaceUser } + >(); + + volunteers.forEach((volunteer) => { + const userId = volunteer.user._id.toString(); + let totalHours = 0; + + // Filter hoursHistory based on the time frame + if (startDate && endDate) { + totalHours = volunteer.hoursHistory.reduce((sum, record) => { + const recordDate = new Date(record.date); + // Check if the record date is within the specified range + if (recordDate >= startDate && recordDate <= endDate) { + return sum + record.hours; + } + return sum; + }, 0); + } else { + // If "allTime", use hoursVolunteered + totalHours = volunteer.hoursVolunteered; + } + + // Accumulate hours for each user + /* c8 ignore start */ + const existingRecord = userHoursMap.get(userId); + if (existingRecord) { + existingRecord.hoursVolunteered += totalHours; + } else { + userHoursMap.set(userId, { + hoursVolunteered: totalHours, + user: volunteer.user, + }); + } + /* c8 ignore stop */ + }); + + // Convert the accumulated map to an array + const volunteerRanks = Array.from(userHoursMap.values()); + + volunteerRanks.sort((a, b) => b.hoursVolunteered - a.hoursVolunteered); + + // Assign ranks, accounting for ties + const rankedVolunteers = []; + let currentRank = 1; + let lastHours = -1; + + for (const volunteer of volunteerRanks) { + if (volunteer.hoursVolunteered !== lastHours) { + currentRank = rankedVolunteers.length + 1; // New rank + } + + rankedVolunteers.push({ + rank: currentRank, + user: volunteer.user, + hoursVolunteered: volunteer.hoursVolunteered, + }); + + lastHours = volunteer.hoursVolunteered; // Update lastHours + } + + // Sort the ranked volunteers based on the orderBy field + + if (orderBy === "hours_ASC") { + rankedVolunteers.sort((a, b) => a.hoursVolunteered - b.hoursVolunteered); + } else if (orderBy === "hours_DESC") { + rankedVolunteers.sort((a, b) => b.hoursVolunteered - a.hoursVolunteered); + } + + // Filter by name + if (nameContains) { + return rankedVolunteers.filter((volunteer) => { + const fullName = + `${volunteer.user.firstName} ${volunteer.user.lastName}`.toLowerCase(); + return fullName.includes(nameContains.toLowerCase()); + }); + } + + return limit ? rankedVolunteers.slice(0, limit) : rankedVolunteers; +}; diff --git a/src/resolvers/Query/groupChatById.ts b/src/resolvers/Query/groupChatById.ts deleted file mode 100644 index 43a00ce65d..0000000000 --- a/src/resolvers/Query/groupChatById.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { GroupChat } from "../../models"; -import { CHAT_NOT_FOUND_ERROR } from "../../constants"; - -/** - * This query will fetch all messages for a certain direct chat for the user from database. - * @param _parent- - * @param args - An object that contains `id` of the direct chat. - * @returns A `directChatsMessages` object that holds all of the messages from the specified direct chat. - * If the `directChatsMessages` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ - -export const groupChatById: QueryResolvers["groupChatById"] = async ( - _parent, - args, -) => { - const directChat = await GroupChat.findById(args.id).lean(); - - if (!directChat) { - throw new errors.NotFoundError( - CHAT_NOT_FOUND_ERROR.DESC, - CHAT_NOT_FOUND_ERROR.CODE, - CHAT_NOT_FOUND_ERROR.PARAM, - ); - } - - return directChat; -}; diff --git a/src/resolvers/Query/groupChatsByUserId.ts b/src/resolvers/Query/groupChatsByUserId.ts deleted file mode 100644 index a3b3310d3e..0000000000 --- a/src/resolvers/Query/groupChatsByUserId.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; -import { errors } from "../../libraries"; -import { GroupChat } from "../../models"; -/** - * This query will fetch all the Direct chats for the current user from the database. - * @param _parent- - * @param args - An object that contains `id` of the user. - * @returns An object `GroupChat` that contains all direct chats of the current user. - * If the `directChats` object is null then it throws `NotFoundError` error. - * @remarks You can learn about GraphQL `Resolvers` - * {@link https://www.apollographql.com/docs/apollo-server/data/resolvers/ | here}. - */ -export const groupChatsByUserId: QueryResolvers["groupChatsByUserId"] = async ( - _parent, - args, -) => { - const groupChats = await GroupChat.find({ - users: args.id, - }).lean(); - - if (groupChats.length === 0) { - throw new errors.NotFoundError( - "Group Chats not found", - "groupChats.notFound", - "groupChats", - ); - } - - return groupChats; -}; diff --git a/src/resolvers/Query/helperFunctions/getSort.ts b/src/resolvers/Query/helperFunctions/getSort.ts index d3f68a704c..a00bde9a21 100644 --- a/src/resolvers/Query/helperFunctions/getSort.ts +++ b/src/resolvers/Query/helperFunctions/getSort.ts @@ -10,6 +10,8 @@ import type { CampaignOrderByInput, FundOrderByInput, ActionItemsOrderByInput, + EventVolunteersOrderByInput, + VolunteerMembershipOrderByInput, } from "../../../types/generatedGraphQLTypes"; export const getSort = ( @@ -24,6 +26,8 @@ export const getSort = ( | CampaignOrderByInput | PledgeOrderByInput | ActionItemsOrderByInput + | EventVolunteersOrderByInput + | VolunteerMembershipOrderByInput > | undefined, ): @@ -335,6 +339,18 @@ export const getSort = ( }; break; + case "hoursVolunteered_ASC": + sortPayload = { + hoursVolunteered: 1, + }; + break; + + case "hoursVolunteered_DESC": + sortPayload = { + hoursVolunteered: -1, + }; + break; + default: break; } diff --git a/src/resolvers/Query/helperFunctions/getWhere.ts b/src/resolvers/Query/helperFunctions/getWhere.ts index e2288ee6cb..56207568e4 100644 --- a/src/resolvers/Query/helperFunctions/getWhere.ts +++ b/src/resolvers/Query/helperFunctions/getWhere.ts @@ -13,6 +13,7 @@ import type { CampaignWhereInput, PledgeWhereInput, ActionItemCategoryWhereInput, + EventVolunteerWhereInput, } from "../../../types/generatedGraphQLTypes"; /** @@ -43,7 +44,8 @@ export const getWhere = ( CampaignWhereInput & FundWhereInput & PledgeWhereInput & - VenueWhereInput + VenueWhereInput & + EventVolunteerWhereInput > > | undefined, @@ -764,21 +766,18 @@ export const getWhere = ( }; } - // Returns objects where volunteerId is present in volunteers list - if (where.volunteerId) { + // Returns object with provided is_disabled condition + if (where.is_disabled !== undefined) { wherePayload = { ...wherePayload, - volunteers: { - $in: [where.volunteerId], - }, + isDisabled: where.is_disabled, }; } - // Returns object with provided is_disabled condition - if (where.is_disabled !== undefined) { + if (where.hasAccepted !== undefined) { wherePayload = { ...wherePayload, - isDisabled: where.is_disabled, + hasAccepted: where.hasAccepted, }; } diff --git a/src/resolvers/Query/index.ts b/src/resolvers/Query/index.ts index fc878303d8..534dec83ce 100644 --- a/src/resolvers/Query/index.ts +++ b/src/resolvers/Query/index.ts @@ -2,6 +2,7 @@ import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; import { isSampleOrganization } from "../Query/organizationIsSample"; import { actionItemCategoriesByOrganization } from "./actionItemCategoriesByOrganization"; import { actionItemsByEvent } from "./actionItemsByEvent"; +import { actionItemsByUser } from "./actionItemsByUser"; import { actionItemsByOrganization } from "./actionItemsByOrganization"; import { advertisementsConnection } from "./advertisementsConnection"; import { agendaCategory } from "./agendaCategory"; @@ -13,14 +14,12 @@ import { getAgendaSection } from "./getAgendaSection"; import { checkAuth } from "./checkAuth"; import { customDataByOrganization } from "./customDataByOrganization"; import { customFieldsByOrganization } from "./customFieldsByOrganization"; -import { directChatsByUserID } from "./directChatsByUserID"; -import { directChatsMessagesByChatID } from "./directChatsMessagesByChatID"; -import { directChatById } from "./directChatById"; -import { groupChatById } from "./groupChatById"; -import { groupChatsByUserId } from "./groupChatsByUserId"; +import { chatById } from "./chatById"; +import { chatsByUserId } from "./chatsByUserId"; import { event } from "./event"; import { eventsByOrganization } from "./eventsByOrganization"; import { eventsByOrganizationConnection } from "./eventsByOrganizationConnection"; +import { getEventVolunteers } from "./getEventVolunteers"; import { getEventVolunteerGroups } from "./getEventVolunteerGroups"; import { fundsByOrganization } from "./fundsByOrganization"; import { getAllAgendaItems } from "./getAllAgendaItems"; @@ -35,7 +34,6 @@ import { getPledgesByUserId } from "./getPledgesByUserId"; import { getPlugins } from "./getPlugins"; import { getlanguage } from "./getlanguage"; import { getUserTag } from "./getUserTag"; -import { getUserTagAncestors } from "./getUserTagAncestors"; import { me } from "./me"; import { myLanguage } from "./myLanguage"; import { organizations } from "./organizations"; @@ -53,8 +51,14 @@ import { getEventAttendeesByEventId } from "./getEventAttendeesByEventId"; import { getVenueByOrgId } from "./getVenueByOrgId"; import { getAllNotesForAgendaItem } from "./getAllNotesForAgendaItem"; import { getNoteById } from "./getNoteById"; +import { eventsAttendedByUser } from "./eventsAttendedByUser"; +import { getRecurringEvents } from "./getRecurringEvents"; +import { getVolunteerMembership } from "./getVolunteerMembership"; +import { getVolunteerRanks } from "./getVolunteerRanks"; + export const Query: QueryResolvers = { actionItemsByEvent, + actionItemsByUser, agendaCategory, getAgendaItem, getAgendaSection, @@ -68,11 +72,8 @@ export const Query: QueryResolvers = { getCommunityData, customFieldsByOrganization, customDataByOrganization, - directChatsByUserID, - directChatsMessagesByChatID, - directChatById, - groupChatById, - groupChatsByUserId, + chatById, + chatsByUserId, event, eventsByOrganization, eventsByOrganizationConnection, @@ -81,13 +82,14 @@ export const Query: QueryResolvers = { getDonationByOrgId, getDonationByOrgIdConnection, getEventInvitesByUserId, + getEventVolunteers, getEventVolunteerGroups, getAllNotesForAgendaItem, getNoteById, getlanguage, getPlugins, + getRecurringEvents, getUserTag, - getUserTagAncestors, isSampleOrganization, me, myLanguage, @@ -108,4 +110,7 @@ export const Query: QueryResolvers = { getEventAttendee, getEventAttendeesByEventId, getVenueByOrgId, + eventsAttendedByUser, + getVolunteerMembership, + getVolunteerRanks, }; diff --git a/src/resolvers/Query/organizationsMemberConnection.ts b/src/resolvers/Query/organizationsMemberConnection.ts index 0a0c29c2dc..7ccc1ea805 100644 --- a/src/resolvers/Query/organizationsMemberConnection.ts +++ b/src/resolvers/Query/organizationsMemberConnection.ts @@ -17,7 +17,7 @@ import { getWhere } from "./helperFunctions/getWhere"; * learn more about Connection {@link https://relay.dev/graphql/connections.htm | here}. */ export const organizationsMemberConnection: QueryResolvers["organizationsMemberConnection"] = - async (_parent, args, context) => { + async (_parent, args) => { const where = getWhere(args.where); const sort = getSort(args.orderBy); @@ -130,7 +130,7 @@ export const organizationsMemberConnection: QueryResolvers["organizationsMemberC employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, - image: user.image ? `${context.apiRootUrl}${user.image}` : null, + image: user.image ?? null, joinedOrganizations: user.joinedOrganizations, lastName: user.lastName, maritalStatus: user.maritalStatus, @@ -141,6 +141,7 @@ export const organizationsMemberConnection: QueryResolvers["organizationsMemberC registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, })); } else { users = usersModel.docs.map((user) => ({ @@ -164,7 +165,7 @@ export const organizationsMemberConnection: QueryResolvers["organizationsMemberC employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, - image: user.image ? `${context.apiRootUrl}${user.image}` : null, + image: user.image ?? null, joinedOrganizations: user.joinedOrganizations, lastName: user.lastName, maritalStatus: user.maritalStatus, @@ -175,6 +176,7 @@ export const organizationsMemberConnection: QueryResolvers["organizationsMemberC registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, })); } diff --git a/src/resolvers/Query/post.ts b/src/resolvers/Query/post.ts index 258c591eb9..9eb82f7453 100644 --- a/src/resolvers/Query/post.ts +++ b/src/resolvers/Query/post.ts @@ -8,10 +8,10 @@ import type { QueryResolvers } from "../../types/generatedGraphQLTypes"; * @param args - An object that contains `id` of the Post. * @returns An object `post`. If the `appLanguageCode` field not found then it throws a `NotFoundError` error. */ -export const post: QueryResolvers["post"] = async (_parent, args, context) => { +export const post: QueryResolvers["post"] = async (_parent, args) => { const post = await Post.findOne({ _id: args.id }) .populate("organization") - .populate("likedBy") + .populate(["likedBy", "file"]) .lean(); if (!post) { @@ -21,12 +21,6 @@ export const post: QueryResolvers["post"] = async (_parent, args, context) => { POST_NOT_FOUND_ERROR.PARAM, ); } - post.imageUrl = post.imageUrl - ? `${context.apiRootUrl}${post.imageUrl}` - : null; - post.videoUrl = post.videoUrl - ? `${context.apiRootUrl}${post.videoUrl}` - : null; return post; }; diff --git a/src/resolvers/Query/user.ts b/src/resolvers/Query/user.ts index c0716be0c3..dc6233a011 100644 --- a/src/resolvers/Query/user.ts +++ b/src/resolvers/Query/user.ts @@ -43,7 +43,6 @@ export const user: QueryResolvers["user"] = async (_parent, args, context) => { return { user: { ...user, - image: user?.image ? `${context.apiRootUrl}${user.image}` : null, organizationsBlockedBy: [], }, appUserProfile: userAppProfile, diff --git a/src/resolvers/Subscription/directMessageChat.ts b/src/resolvers/Subscription/directMessageChat.ts deleted file mode 100644 index 38af5cbd3a..0000000000 --- a/src/resolvers/Subscription/directMessageChat.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { withFilter } from "graphql-subscriptions"; -import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; - -const CHAT_CHANNEL = "CHAT_CHANNEL"; -/** - * This property contained a `subscribe` field, which is used to subscribe - * the user to get updates for the `CHAT_CHANNEL` event. - * @remarks To control updates on a per-client basis, the function uses the `withFilter` - * method imported from `apollo-server-express` module. - * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. - */ -export const directMessageChat: SubscriptionResolvers["directMessageChat"] = { - // @ts-expect-error-ts-ignore - subscribe: withFilter( - (_parent, _args, context) => context.pubsub.asyncIterator(CHAT_CHANNEL), - - (payload) => payload?.directMessageChat, - ), -}; diff --git a/src/resolvers/Subscription/index.ts b/src/resolvers/Subscription/index.ts index c981720fcb..f2f19e4836 100644 --- a/src/resolvers/Subscription/index.ts +++ b/src/resolvers/Subscription/index.ts @@ -1,11 +1,7 @@ import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; -import { directMessageChat } from "./directMessageChat"; -import { messageSentToDirectChat } from "./messageSentToDirectChat"; -import { messageSentToGroupChat } from "./messageSentToGroupChat"; +import { messageSentToChat } from "./messageSentToChat"; import { onPluginUpdate } from "./onPluginUpdate"; export const Subscription: SubscriptionResolvers = { - directMessageChat, - messageSentToDirectChat, - messageSentToGroupChat, + messageSentToChat, onPluginUpdate, }; diff --git a/src/resolvers/Subscription/messageSentToChat.ts b/src/resolvers/Subscription/messageSentToChat.ts new file mode 100644 index 0000000000..936fd104de --- /dev/null +++ b/src/resolvers/Subscription/messageSentToChat.ts @@ -0,0 +1,43 @@ +import { withFilter } from "graphql-subscriptions"; +import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; +import { Chat } from "../../models"; + +const MESSAGE_SENT_TO_CHAT = "MESSAGE_SENT_TO_CHAT"; + +export const filterFunction = async function ( + payload: { messageSentToChat: { chatMessageBelongsTo: string } }, + variables: { userId: string }, +): Promise { + const currentUserId = variables.userId.toString(); + const chatId = payload.messageSentToChat.chatMessageBelongsTo; + + const chat = await Chat.findOne({ + _id: chatId, + }).lean(); + + if (chat) { + const currentUserIsChatMember = chat.users.some((user) => + user.equals(currentUserId), + ); + return currentUserIsChatMember; + } else { + return false; + } +}; +/** + * This property included a `subscribe` method, which is used to + * subscribe the `receiver` and `sender` to receive Chat updates. + * + * @remarks To control updates on a per-client basis, the function uses the `withFilter` + * method imported from `apollo-server-express` module. + * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. + */ +export const messageSentToChat: SubscriptionResolvers["messageSentToChat"] = { + // @ts-expect-error-ts-ignore + subscribe: withFilter( + (_parent, _args, context) => + context.pubsub.asyncIterator([MESSAGE_SENT_TO_CHAT]), + + (payload, variables) => filterFunction(payload, variables), + ), +}; diff --git a/src/resolvers/Subscription/messageSentToDirectChat.ts b/src/resolvers/Subscription/messageSentToDirectChat.ts deleted file mode 100644 index 55ce56e603..0000000000 --- a/src/resolvers/Subscription/messageSentToDirectChat.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { withFilter } from "graphql-subscriptions"; -import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; - -const MESSAGE_SENT_TO_DIRECT_CHAT = "MESSAGE_SENT_TO_DIRECT_CHAT"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const filterFunction = function (payload: any, variables: any): boolean { - const currentUserId = variables.userId.toString(); - console.log( - currentUserId, - payload.messageSentToDirectChat.receiver.toString(), - payload.messageSentToDirectChat.sender.toString(), - ); - return ( - currentUserId === payload.messageSentToDirectChat.receiver.toString() || - currentUserId === payload.messageSentToDirectChat.sender.toString() - ); -}; -/** - * This property included a `subscribe` method, which is used to - * subscribe the `receiver` and `sender` to receive Direct Chat updates. - * - * @remarks To control updates on a per-client basis, the function uses the `withFilter` - * method imported from `apollo-server-express` module. - * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. - */ -export const messageSentToDirectChat: SubscriptionResolvers["messageSentToDirectChat"] = - { - // @ts-expect-error-ts-ignore - subscribe: withFilter( - (_parent, _args, context) => - context.pubsub.asyncIterator([MESSAGE_SENT_TO_DIRECT_CHAT]), - - (payload, variables) => filterFunction(payload, variables), - ), - }; diff --git a/src/resolvers/Subscription/messageSentToGroupChat.ts b/src/resolvers/Subscription/messageSentToGroupChat.ts deleted file mode 100644 index ec45eb30c2..0000000000 --- a/src/resolvers/Subscription/messageSentToGroupChat.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { withFilter } from "graphql-subscriptions"; -import type { SubscriptionResolvers } from "../../types/generatedGraphQLTypes"; -import { GroupChat } from "../../models"; - -const MESSAGE_SENT_TO_GROUP_CHAT = "MESSAGE_SENT_TO_GROUP_CHAT"; - -/** - * This function is used to filter the subscription payload based on the current user's membership in the group chat. - * - * @param payload - The payload of the subscription message. - * @param context - The context object containing the current user's ID. - * @returns A promise that resolves to a boolean value indicating whether the current user is a member of the group chat. - */ -export const filterFunction = async function ( - payload: any, - variables: any, -): Promise { - const currentUserId = variables.userId; - const groupChatId = payload.messageSentToGroupChat.groupChatMessageBelongsTo; - - const groupChat = await GroupChat.findOne({ - _id: groupChatId, - }).lean(); - - if (groupChat) { - const currentUserIsGroupChatMember = groupChat.users.some((user) => - user.equals(currentUserId), - ); - return currentUserIsGroupChatMember; - } else { - return false; - } -}; -/** - * This property included a `subscribe` method, which is used to - * subscribe the `current_user` to get updates for Group chats. - * - * @remarks To control updates on a per-client basis, the function uses the `withFilter` - * method imported from `apollo-server-express` module. - * You can learn about `subscription` {@link https://www.apollographql.com/docs/apollo-server/data/subscriptions/ | here }. - */ -export const messageSentToGroupChat: SubscriptionResolvers["messageSentToGroupChat"] = - { - // @ts-expect-error-ts-ignore - subscribe: withFilter( - (_parent, _args, context) => - context.pubsub.asyncIterator([MESSAGE_SENT_TO_GROUP_CHAT]), - - (payload, variables) => filterFunction(payload, variables), - ), - }; diff --git a/src/resolvers/User/index.ts b/src/resolvers/User/index.ts index 538fe582cf..79d556c2b3 100644 --- a/src/resolvers/User/index.ts +++ b/src/resolvers/User/index.ts @@ -1,8 +1,8 @@ import type { UserResolvers } from "../../types/generatedGraphQLTypes"; -// import { tagsAssignedWith } from "./tagsAssignedWith"; +import { tagsAssignedWith } from "./tagsAssignedWith"; import { posts } from "./posts"; export const User: UserResolvers = { - // tagsAssignedWith, + tagsAssignedWith, posts, }; diff --git a/src/resolvers/User/tagsAssignedWith.ts b/src/resolvers/User/tagsAssignedWith.ts new file mode 100644 index 0000000000..92212b1633 --- /dev/null +++ b/src/resolvers/User/tagsAssignedWith.ts @@ -0,0 +1,163 @@ +import type { UserResolvers } from "../../types/generatedGraphQLTypes"; +import type { + InterfaceOrganizationTagUser, + InterfaceTagUser, +} from "../../models"; +import { TagUser } from "../../models"; +import { + type DefaultGraphQLArgumentError, + type ParseGraphQLConnectionCursorArguments, + type ParseGraphQLConnectionCursorResult, + getCommonGraphQLConnectionFilter, + getCommonGraphQLConnectionSort, + parseGraphQLConnectionArguments, + transformToDefaultGraphQLConnection, +} from "../../utilities/graphQLConnection"; +import { GraphQLError } from "graphql"; +import { MAXIMUM_FETCH_LIMIT } from "../../constants"; +import type { Types } from "mongoose"; + +/** + * Resolver function for the `tagsAssignedWith` field of a `User`. + * + * This resolver is used to resolve the `tagsAssignedWith` field of a `User` type. + * + * @param parent - The parent object representing the user. It contains information about the user, including the ID of the user. + * @param args - The arguments provided to the field. These arguments are used to filter, sort, and paginate the tags assigned to the user. + * @returns A promise that resolves to a connection object containing the tags assigned to the user. + * + * @see TagUser - The TagUser model used to interact with the tag users collection in the database. + * @see parseGraphQLConnectionArguments - The function used to parse the GraphQL connection arguments (filter, sort, pagination). + * @see transformToDefaultGraphQLConnection - The function used to transform the list of tags assigned to the user into a connection object. + * @see getCommonGraphQLConnectionFilter - The function used to get the common filter object for the GraphQL connection. + * @see getCommonGraphQLConnectionSort - The function used to get the common sort object for the GraphQL connection. + * @see MAXIMUM_FETCH_LIMIT - The maximum number of users that can be fetched in a single request. + * @see GraphQLError - The error class used to throw GraphQL errors. + * @see UserTagResolvers - The type definition for the resolvers of the User fields. + * + */ +export const tagsAssignedWith: UserResolvers["tagsAssignedWith"] = async ( + parent, + args, +) => { + const parseGraphQLConnectionArgumentsResult = + await parseGraphQLConnectionArguments({ + args, + parseCursor: /* c8 ignore start */ (args) => + parseCursor({ + ...args, + userId: parent._id, + }), + /* c8 ignore stop */ + maximumLimit: MAXIMUM_FETCH_LIMIT, + }); + + if (!parseGraphQLConnectionArgumentsResult.isSuccessful) { + throw new GraphQLError("Invalid arguments provided.", { + extensions: { + code: "INVALID_ARGUMENTS", + errors: parseGraphQLConnectionArgumentsResult.errors, + }, + }); + } + + const { parsedArgs } = parseGraphQLConnectionArgumentsResult; + + const filter = getCommonGraphQLConnectionFilter({ + cursor: parsedArgs.cursor, + direction: parsedArgs.direction, + }); + + const sort = getCommonGraphQLConnectionSort({ + direction: parsedArgs.direction, + }); + + const [objectList, totalCount] = await Promise.all([ + TagUser.find({ + ...filter, + userId: parent._id, + organizationId: args.organizationId, + }) + .sort(sort) + .limit(parsedArgs.limit) + .populate("tagId") + .lean() + .exec(), + + TagUser.find({ + userId: parent._id, + organizationId: args.organizationId, + }) + .countDocuments() + .exec(), + ]); + + return transformToDefaultGraphQLConnection< + ParsedCursor, + InterfaceTagUser, + InterfaceOrganizationTagUser + >({ + createNode: (object) => { + return object.tagId as InterfaceOrganizationTagUser; + }, + objectList, + parsedArgs, + totalCount, + }); +}; + +/* +This is typescript type of the parsed cursor for this connection resolver. +*/ +type ParsedCursor = string; + +/** + * Parses the cursor value for the `tagsAssignedWith` connection resolver. + * + * This function is used to parse the cursor value provided to the `tagsAssignedWith` connection resolver. + * + * @param cursorValue - The cursor value to be parsed. + * @param cursorName - The name of the cursor argument. + * @param cursorPath - The path of the cursor argument in the GraphQL query. + * @param userId - The ID of the user for which assigned tags are being queried. + * @returns An object containing the parsed cursor value or an array of errors if the cursor value is invalid. + * + * @see TagUser - The TagUser model used to interact with the tag users collection in the database. + * @see DefaultGraphQLArgumentError - The type definition for the default GraphQL argument error. + * @see ParseGraphQLConnectionCursorArguments - The type definition for the arguments provided to the parseCursor function. + * @see ParseGraphQLConnectionCursorResult - The type definition for the result of the parseCursor function. + * + */ +export const parseCursor = async ({ + cursorValue, + cursorName, + cursorPath, + userId, +}: ParseGraphQLConnectionCursorArguments & { + userId: string | Types.ObjectId; +}): ParseGraphQLConnectionCursorResult => { + const errors: DefaultGraphQLArgumentError[] = []; + const tagUser = await TagUser.findOne({ + _id: cursorValue, + userId, + }); + + if (!tagUser) { + errors.push({ + message: `Argument ${cursorName} is an invalid cursor.`, + path: cursorPath, + }); + } + + if (errors.length !== 0) { + return { + errors, + isSuccessful: false, + }; + } + + return { + isSuccessful: true, + parsedCursor: cursorValue, + }; +}; diff --git a/src/resolvers/UserTag/ancestorTags.ts b/src/resolvers/UserTag/ancestorTags.ts new file mode 100644 index 0000000000..890a6cd51e --- /dev/null +++ b/src/resolvers/UserTag/ancestorTags.ts @@ -0,0 +1,41 @@ +import type { InterfaceOrganizationTagUser } from "../../models"; +import { OrganizationTagUser } from "../../models"; +import type { UserTagResolvers } from "../../types/generatedGraphQLTypes"; + +/** + * Resolver function for the `ancestorTags` field of an `OrganizationTagUser`. + * + * This function retrieves the ancestor tags of a specific organization user tag by recursively finding + * each parent tag until the root tag (where parentTagId is null) is reached. It then reverses the order, + * appends the current tag at the end, and returns the final array of tags. + * + * @param parent - The parent object representing the user tag. It contains information about the tag, including its ID and parentTagId. + * @returns A promise that resolves to the ordered array of ancestor tag documents found in the database. + */ +export const ancestorTags: UserTagResolvers["ancestorTags"] = async ( + parent, +) => { + // Initialize an array to collect the ancestor tags + const ancestorTags: InterfaceOrganizationTagUser[] = []; + + // Start with the current parentTagId + let currentParentId = parent.parentTagId; + + // Traverse up the hierarchy to find all ancestorTags + while (currentParentId) { + const tag = await OrganizationTagUser.findById(currentParentId).lean(); + + if (!tag) break; + + // Add the found tag to the ancestorTags array + ancestorTags.push(tag); + + // Move up to the next parent + currentParentId = tag.parentTagId; + } + + // Reverse the ancestorTags to have the root tag first, then append the current tag + ancestorTags.reverse(); + + return ancestorTags; +}; diff --git a/src/resolvers/UserTag/childTags.ts b/src/resolvers/UserTag/childTags.ts index ae95fb2b16..3c886d35d2 100644 --- a/src/resolvers/UserTag/childTags.ts +++ b/src/resolvers/UserTag/childTags.ts @@ -2,9 +2,7 @@ import type { UserTagResolvers } from "../../types/generatedGraphQLTypes"; import type { InterfaceOrganizationTagUser } from "../../models"; import { OrganizationTagUser } from "../../models"; import { - getCommonGraphQLConnectionFilter, - getCommonGraphQLConnectionSort, - parseGraphQLConnectionArguments, + parseGraphQLConnectionArgumentsWithSortedByAndWhere, transformToDefaultGraphQLConnection, type DefaultGraphQLArgumentError, type ParseGraphQLConnectionCursorArguments, @@ -13,6 +11,12 @@ import { import { GraphQLError } from "graphql"; import { MAXIMUM_FETCH_LIMIT } from "../../constants"; import type { Types } from "mongoose"; +import { + getUserTagGraphQLConnectionFilter, + getUserTagGraphQLConnectionSort, + parseUserTagSortedBy, + parseUserTagWhere, +} from "../../utilities/userTagsPaginationUtils"; /** * Resolver function for the `childTags` field of a `UserTag`. @@ -26,8 +30,8 @@ import type { Types } from "mongoose"; * @see OrganizationTagUser - The OrganizationTagUser model used to interact with the organization tag users collection in the database. * @see parseGraphQLConnectionArguments - The function used to parse the GraphQL connection arguments (filter, sort, pagination). * @see transformToDefaultGraphQLConnection - The function used to transform the list of child tags into a connection object. - * @see getCommonGraphQLConnectionFilter - The function used to get the common filter object for the GraphQL connection. - * @see getCommonGraphQLConnectionSort - The function used to get the common sort object for the GraphQL connection. + * @see getGraphQLConnectionFilter - The function used to get the common filter object for the GraphQL connection. + * @see getGraphQLConnectionSort - The function used to get the common sort object for the GraphQL connection. * @see MAXIMUM_FETCH_LIMIT - The maximum number of child tags that can be fetched in a single request. * @see GraphQLError - The error class used to throw GraphQL errors. * @see UserTagResolvers - The type definition for the resolvers of the UserTag fields. @@ -37,14 +41,20 @@ export const childTags: UserTagResolvers["childTags"] = async ( parent, args, ) => { + const parseWhereResult = parseUserTagWhere(args.where); + const parseSortedByResult = parseUserTagSortedBy(args.sortedBy); + const parseGraphQLConnectionArgumentsResult = - await parseGraphQLConnectionArguments({ + await parseGraphQLConnectionArgumentsWithSortedByAndWhere({ args, - parseCursor: (args) => + parseSortedByResult, + parseWhereResult, + parseCursor: /* c8 ignore start */ (args) => parseCursor({ ...args, parentTagId: parent._id, }), + /* c8 ignore stop */ maximumLimit: MAXIMUM_FETCH_LIMIT, }); @@ -59,18 +69,27 @@ export const childTags: UserTagResolvers["childTags"] = async ( const { parsedArgs } = parseGraphQLConnectionArgumentsResult; - const filter = getCommonGraphQLConnectionFilter({ + const objectListFilter = getUserTagGraphQLConnectionFilter({ cursor: parsedArgs.cursor, direction: parsedArgs.direction, + sortById: parsedArgs.sort.sortById, + nameStartsWith: parsedArgs.filter.nameStartsWith, }); - const sort = getCommonGraphQLConnectionSort({ + // don't use _id as a filter in while counting the documents + // _id is only used for pagination + const totalCountFilter = Object.fromEntries( + Object.entries(objectListFilter).filter(([key]) => key !== "_id"), + ); + + const sort = getUserTagGraphQLConnectionSort({ direction: parsedArgs.direction, + sortById: parsedArgs.sort.sortById, }); const [objectList, totalCount] = await Promise.all([ OrganizationTagUser.find({ - ...filter, + ...objectListFilter, parentTagId: parent._id, }) .sort(sort) @@ -78,6 +97,7 @@ export const childTags: UserTagResolvers["childTags"] = async ( .lean() .exec(), OrganizationTagUser.find({ + ...totalCountFilter, parentTagId: parent._id, }) .countDocuments() diff --git a/src/resolvers/UserTag/index.ts b/src/resolvers/UserTag/index.ts index ee65404610..c2e8c73c5d 100644 --- a/src/resolvers/UserTag/index.ts +++ b/src/resolvers/UserTag/index.ts @@ -2,11 +2,15 @@ import type { UserTagResolvers } from "../../types/generatedGraphQLTypes"; import { childTags } from "./childTags"; import { organization } from "./organization"; import { parentTag } from "./parentTag"; +import { ancestorTags } from "./ancestorTags"; import { usersAssignedTo } from "./usersAssignedTo"; +import { usersToAssignTo } from "./usersToAssignTo"; export const UserTag: UserTagResolvers = { childTags, organization, parentTag, + ancestorTags, usersAssignedTo, + usersToAssignTo, }; diff --git a/src/resolvers/UserTag/usersAssignedTo.ts b/src/resolvers/UserTag/usersAssignedTo.ts index ebc8dd20a6..8722c94af2 100644 --- a/src/resolvers/UserTag/usersAssignedTo.ts +++ b/src/resolvers/UserTag/usersAssignedTo.ts @@ -5,14 +5,18 @@ import { type DefaultGraphQLArgumentError, type ParseGraphQLConnectionCursorArguments, type ParseGraphQLConnectionCursorResult, - getCommonGraphQLConnectionFilter, - getCommonGraphQLConnectionSort, - parseGraphQLConnectionArguments, + parseGraphQLConnectionArgumentsWithSortedByAndWhere, transformToDefaultGraphQLConnection, } from "../../utilities/graphQLConnection"; import { GraphQLError } from "graphql"; import { MAXIMUM_FETCH_LIMIT } from "../../constants"; -import type { Types } from "mongoose"; +import { Types } from "mongoose"; +import { + parseUserTagSortedBy, + parseUserTagMemberWhere, + getUserTagMemberGraphQLConnectionFilter, + getUserTagGraphQLConnectionSort, +} from "../../utilities/userTagsPaginationUtils"; /** * Resolver function for the `usersAssignedTo` field of a `UserTag`. @@ -37,14 +41,20 @@ export const usersAssignedTo: UserTagResolvers["usersAssignedTo"] = async ( parent, args, ) => { + const parseWhereResult = parseUserTagMemberWhere(args.where); + const parseSortedByResult = parseUserTagSortedBy(args.sortedBy); + const parseGraphQLConnectionArgumentsResult = - await parseGraphQLConnectionArguments({ + await parseGraphQLConnectionArgumentsWithSortedByAndWhere({ args, - parseCursor: (args) => + parseSortedByResult, + parseWhereResult, + parseCursor: /* c8 ignore start */ (args) => parseCursor({ ...args, tagId: parent._id, }), + /* c8 ignore stop */ maximumLimit: MAXIMUM_FETCH_LIMIT, }); @@ -59,31 +69,91 @@ export const usersAssignedTo: UserTagResolvers["usersAssignedTo"] = async ( const { parsedArgs } = parseGraphQLConnectionArgumentsResult; - const filter = getCommonGraphQLConnectionFilter({ + const objectListFilter = getUserTagMemberGraphQLConnectionFilter({ cursor: parsedArgs.cursor, direction: parsedArgs.direction, + sortById: parsedArgs.sort.sortById, + firstNameStartsWith: parsedArgs.filter.firstNameStartsWith, + lastNameStartsWith: parsedArgs.filter.lastNameStartsWith, }); - const sort = getCommonGraphQLConnectionSort({ + // Separate the _id filter from the rest + // _id filter will be applied on the TagUser model + // the rest on the User model referenced by the userId field + const { _id: tagUserIdFilter, ...userFilter } = objectListFilter; + const tagUserFilter = tagUserIdFilter ? { _id: tagUserIdFilter } : {}; + + const sort = getUserTagGraphQLConnectionSort({ direction: parsedArgs.direction, + sortById: parsedArgs.sort.sortById, }); + // create the filter object to match the user documents in the pipeline + const userMatchFilter = Object.fromEntries( + Object.entries(userFilter).map(([key, value]) => [`user.${key}`, value]), + ); + + // commonPipeline object for the query + const commonPipeline = [ + // Perform a left join with User collection on _id + { + $lookup: { + from: "users", + localField: "userId", + foreignField: "_id", + as: "user", + }, + }, + { + $unwind: "$user", + }, + // apply the userFilter to the user + { + $match: { + ...userMatchFilter, + }, + }, + ]; + + // we want to assign the userFilter to the user referenced by userId + // and the _id filter (specified by the after/before) to the TagUser document const [objectList, totalCount] = await Promise.all([ - TagUser.find({ - ...filter, - tagId: parent._id, - }) - .sort(sort) - .limit(parsedArgs.limit) - .populate("userId") - .lean() - .exec(), - - TagUser.find({ - tagId: parent._id, - }) - .countDocuments() - .exec(), + // First aggregation to get the TagUser list matching the filter criteria + TagUser.aggregate([ + { + $match: { + ...tagUserFilter, + tagId: new Types.ObjectId(parent._id), + }, + }, + ...commonPipeline, + { + $sort: sort, + }, + { + $limit: parsedArgs.limit, + }, + { + $addFields: { userId: "$user" }, + }, + { + $project: { + user: 0, + }, + }, + ]), + // Second aggregation to count the total TagUser documents matching the filter criteria + TagUser.aggregate([ + { + $match: { + tagId: new Types.ObjectId(parent._id), + }, + }, + ...commonPipeline, + { + $count: "totalCount", + }, + ]).then((res) => res[0]?.totalCount || 0), ]); return transformToDefaultGraphQLConnection< diff --git a/src/resolvers/UserTag/usersToAssignTo.ts b/src/resolvers/UserTag/usersToAssignTo.ts new file mode 100644 index 0000000000..dfadc04264 --- /dev/null +++ b/src/resolvers/UserTag/usersToAssignTo.ts @@ -0,0 +1,199 @@ +import type { UserTagResolvers } from "../../types/generatedGraphQLTypes"; +import type { InterfaceUser } from "../../models"; +import { User } from "../../models"; +import type { + DefaultGraphQLArgumentError, + ParseGraphQLConnectionCursorArguments, + ParseGraphQLConnectionCursorResult, +} from "../../utilities/graphQLConnection"; + +import { + getCommonGraphQLConnectionSort, + parseGraphQLConnectionArgumentsWithWhere, + transformToDefaultGraphQLConnection, +} from "../../utilities/graphQLConnection"; + +import { GraphQLError } from "graphql"; +import { MAXIMUM_FETCH_LIMIT } from "../../constants"; +import { Types } from "mongoose"; +import { + getUserTagMemberGraphQLConnectionFilter, + parseUserTagMemberWhere, +} from "../../utilities/userTagsPaginationUtils"; + +/** + * Resolver function for the `usersToAssignTo` field of a `UserTag`. + * + * @param parent - The parent object representing the user tag. It contains information about the user tag, including the ID of the user tag. + * @param args - The arguments provided to the field. These arguments are used to filter, sort, and paginate the users assigned to the user tag. + * @returns A promise that resolves to a connection object containing the users assigned to the user tag. + * + * @see User - The User model used to interact with the users collection in the database. + * @see parseGraphQLConnectionArguments - The function used to parse the GraphQL connection arguments (filter, sort, pagination). + * @see transformToDefaultGraphQLConnection - The function used to transform the list of users assigned to the user tag into a connection object. + * @see getGraphQLConnectionFilter - The function used to get the filter object for the GraphQL connection. + * @see getCommonGraphQLConnectionSort - The function used to get the common sort object for the GraphQL connection. + * @see MAXIMUM_FETCH_LIMIT - The maximum number of users that can be fetched in a single request. + * @see GraphQLError - The error class used to throw GraphQL errors. + * @see UserResolvers - The type definition for the resolvers of the UserTag fields. + * + */ +export const usersToAssignTo: UserTagResolvers["usersToAssignTo"] = async ( + parent, + args, +) => { + const parseWhereResult = parseUserTagMemberWhere(args.where); + + const parseGraphQLConnectionArgumentsResult = + await parseGraphQLConnectionArgumentsWithWhere({ + args, + parseWhereResult, + parseCursor: /* c8 ignore start */ (args) => + parseCursor({ + ...args, + }), + /* c8 ignore stop */ + maximumLimit: MAXIMUM_FETCH_LIMIT, + }); + + if (!parseGraphQLConnectionArgumentsResult.isSuccessful) { + throw new GraphQLError("Invalid arguments provided.", { + extensions: { + code: "INVALID_ARGUMENTS", + errors: parseGraphQLConnectionArgumentsResult.errors, + }, + }); + } + + const { parsedArgs } = parseGraphQLConnectionArgumentsResult; + + const objectListFilter = getUserTagMemberGraphQLConnectionFilter({ + cursor: parsedArgs.cursor, + direction: parsedArgs.direction, + sortById: "DESCENDING", + firstNameStartsWith: parsedArgs.where.firstNameStartsWith, + lastNameStartsWith: parsedArgs.where.lastNameStartsWith, + }); + + // don't use _id as a filter in while counting the documents + // _id is only used for pagination + const totalCountFilter = Object.fromEntries( + Object.entries(objectListFilter).filter(([key]) => key !== "_id"), + ); + + const sort = getCommonGraphQLConnectionSort({ + direction: parsedArgs.direction, + }); + + const commonPipeline = [ + // Perform a left join with TagUser collection on userId + { + $lookup: { + from: "tagusers", // Name of the collection holding TagUser documents + localField: "_id", + foreignField: "userId", + as: "tagUsers", + }, + }, + // Filter out users that have a tagUser document with the specified tagId + { + $match: { + tagUsers: { + $not: { + $elemMatch: { tagId: new Types.ObjectId(parent._id) }, + }, + }, + }, + }, + ]; + + // Execute the queries using the common pipeline + const [objectList, totalCount] = await Promise.all([ + // First aggregation to get the user list matching the filter criteria + User.aggregate([ + { + $match: { + ...objectListFilter, + joinedOrganizations: { $in: [parent.organizationId] }, + }, + }, + ...commonPipeline, + { + $sort: { ...sort }, + }, + { $limit: parsedArgs.limit }, + ]), + // Second aggregation to count total users matching the filter criteria + User.aggregate([ + { + $match: { + ...totalCountFilter, + joinedOrganizations: { $in: [parent.organizationId] }, + }, + }, + ...commonPipeline, + { $count: "totalCount" }, + ]).then((res) => res[0]?.totalCount || 0), + ]); + + return transformToDefaultGraphQLConnection< + ParsedCursor, + InterfaceUser, + InterfaceUser + >({ + objectList, + parsedArgs, + totalCount, + }); +}; + +/* +This is typescript type of the parsed cursor for this connection resolver. +*/ +type ParsedCursor = string; + +/** + * Parses the cursor value for the `usersToAssignTo` connection resolver. + * + * This function is used to parse the cursor value provided to the `usersToAssignTo` connection resolver. + * + * @param cursorValue - The cursor value to be parsed. + * @param cursorName - The name of the cursor argument. + * @param cursorPath - The path of the cursor argument in the GraphQL query. + * @returns An object containing the parsed cursor value or an array of errors if the cursor value is invalid. + * + * @see User - The User model used to interact with the users collection in the database. + * @see DefaultGraphQLArgumentError - The type definition for the default GraphQL argument error. + * @see ParseGraphQLConnectionCursorArguments - The type definition for the arguments provided to the parseCursor function. + * @see ParseGraphQLConnectionCursorResult - The type definition for the result of the parseCursor function. + * + */ +export const parseCursor = async ({ + cursorValue, + cursorName, + cursorPath, +}: ParseGraphQLConnectionCursorArguments): ParseGraphQLConnectionCursorResult => { + const errors: DefaultGraphQLArgumentError[] = []; + const user = await User.findOne({ + _id: cursorValue, + }); + + if (!user) { + errors.push({ + message: `Argument ${cursorName} is an invalid cursor.`, + path: cursorPath, + }); + } + + if (errors.length !== 0) { + return { + errors, + isSuccessful: false, + }; + } + + return { + isSuccessful: true, + parsedCursor: cursorValue, + }; +}; diff --git a/src/resolvers/index.ts b/src/resolvers/index.ts index 38873057ba..ef021d86ef 100644 --- a/src/resolvers/index.ts +++ b/src/resolvers/index.ts @@ -18,14 +18,11 @@ import { AgendaSection } from "./AgendaSection"; import { AgendaCategory } from "./AgendaCategory"; import { CheckIn } from "./CheckIn"; import { Comment } from "./Comment"; -import { DirectChat } from "./DirectChat"; -import { DirectChatMessage } from "./DirectChatMessage"; +import { Chat } from "./Chat"; +import { ChatMessage } from "./ChatMessage"; import { Event } from "./Event"; -import { EventVolunteer } from "./EventVolunteer"; import { Feedback } from "./Feedback"; import { Fund } from "./Fund"; -import { GroupChat } from "./GroupChat"; -import { GroupChatMessage } from "./GroupChatMessage"; import { MembershipRequest } from "./MembershipRequest"; import { Mutation } from "./Mutation"; import { Organization } from "./Organization"; @@ -50,15 +47,12 @@ const resolvers: Resolvers = { Advertisement, CheckIn, Comment, - DirectChat, - DirectChatMessage, + Chat, + ChatMessage, Event, - EventVolunteer, Feedback, Fund, - GroupChat, UserFamily, - GroupChatMessage, MembershipRequest, Mutation, Organization, @@ -89,8 +83,7 @@ const resolversComposition = { "Mutation.addOrganizationImage": [currentUserExists()], "Mutation.blockPluginCreationBySuperadmin": [currentUserExists()], "Mutation.createComment": [currentUserExists()], - "Mutation.createDirectChat": [currentUserExists()], - "Mutation.createGroupChat": [currentUserExists()], + "Mutation.createChat": [currentUserExists()], "Mutation.createOrganization": [currentUserExists()], "Mutation.createVenue": [currentUserExists()], "Mutation.deleteVenue": [currentUserExists()], diff --git a/src/setup/superAdmin.ts b/src/setup/superAdmin.ts index aeef732b1f..66fb954c45 100644 --- a/src/setup/superAdmin.ts +++ b/src/setup/superAdmin.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/explicit-function-return-type */ import inquirer from "inquirer"; import { isValidEmail } from "./isValidEmail"; @@ -17,7 +16,7 @@ export async function askForSuperAdminEmail(): Promise { name: "email", message: "Enter the email which you wish to assign as the Super Admin of last resort :", - validate: (input: string) => + validate: (input: string): boolean | string => isValidEmail(input) || "Invalid email. Please try again.", }, ]); diff --git a/src/typeDefs/enums.ts b/src/typeDefs/enums.ts index b3e0a8b4c2..e8e294b0ab 100644 --- a/src/typeDefs/enums.ts +++ b/src/typeDefs/enums.ts @@ -141,6 +141,22 @@ export const enums = gql` endDate_DESC } + enum EventVolunteersOrderByInput { + hoursVolunteered_ASC + hoursVolunteered_DESC + } + + enum EventVolunteerGroupOrderByInput { + volunteers_ASC + volunteers_DESC + assignments_ASC + assignments_DESC + } + enum VolunteerMembershipOrderByInput { + createdAt_ASC + createdAt_DESC + } + enum WeekDays { MONDAY TUESDAY @@ -202,6 +218,11 @@ export const enums = gql` MENU } + enum FileVisibility { + PRIVATE + PUBLIC + } + enum ItemType { Regular Note diff --git a/src/typeDefs/errors/createDirectChatError.ts b/src/typeDefs/errors/createDirectChatError.ts deleted file mode 100644 index f2a9b9eb43..0000000000 --- a/src/typeDefs/errors/createDirectChatError.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { gql } from "graphql-tag"; - -/** - * GraphQL schema definition for errors related to creating a direct chat. - */ -export const createDirectChatErrors = gql` - type OrganizationNotFoundError implements Error { - message: String! - } - - type UserNotFoundError implements Error { - message: String! - } - - union CreateDirectChatError = OrganizationNotFoundError | UserNotFoundError -`; diff --git a/src/typeDefs/errors/index.ts b/src/typeDefs/errors/index.ts index a71db2d6e3..7306e51027 100644 --- a/src/typeDefs/errors/index.ts +++ b/src/typeDefs/errors/index.ts @@ -3,7 +3,6 @@ import { connectionError } from "./connectionError"; import { createMemberErrors } from "./createMemberErrors"; import { createAdminErrors } from "./createAdminErrors"; import { createCommentErrors } from "./createCommentErrors"; -import { createDirectChatErrors } from "./createDirectChatError"; /** * Array of all error definitions. @@ -14,5 +13,4 @@ export const errors = [ createMemberErrors, createAdminErrors, createCommentErrors, - createDirectChatErrors, ]; diff --git a/src/typeDefs/inputs.ts b/src/typeDefs/inputs.ts index 65cca30e4d..ae0958f69a 100644 --- a/src/typeDefs/inputs.ts +++ b/src/typeDefs/inputs.ts @@ -16,15 +16,12 @@ export const inputs = gql` userId: ID! } - input createChatInput { - userIds: [ID!]! + input chatInput { + isGroup: Boolean! organizationId: ID - } - - input createGroupChatInput { userIds: [ID!]! - organizationId: ID! - title: String! + name: String + image: String } input createUserFamilyInput { @@ -41,8 +38,9 @@ export const inputs = gql` input CreateActionItemInput { assigneeId: ID! + assigneeType: String! preCompletionNotes: String - allotedHours: Float + allottedHours: Float dueDate: Date eventId: ID } @@ -73,6 +71,7 @@ export const inputs = gql` } input ActionItemWhereInput { + orgId: ID actionItemCategory_id: ID event_id: ID categoryName: String @@ -149,31 +148,54 @@ export const inputs = gql` input EventVolunteerInput { userId: ID! eventId: ID! - groupId: ID! + groupId: ID + } + + input EventVolunteerWhereInput { + id: ID + eventId: ID + groupId: ID + hasAccepted: Boolean + name_contains: String } input EventVolunteerGroupInput { - name: String + name: String! + description: String eventId: ID! + leaderId: ID! volunteersRequired: Int + volunteerUserIds: [ID!]! } input EventVolunteerGroupWhereInput { eventId: ID - volunteerId: ID + userId: ID + orgId: ID + leaderName: String name_contains: String } - input UpdateEventVolunteerInput { + input VolunteerMembershipWhereInput { + eventTitle: String + userName: String + status: String + userId: ID eventId: ID - isAssigned: Boolean - isInvited: Boolean - response: EventVolunteerResponse + groupId: ID + filter: String + } + + input UpdateEventVolunteerInput { + assignments: [ID] + hasAccepted: Boolean + isPublic: Boolean } input UpdateEventVolunteerGroupInput { - eventId: ID + eventId: ID! name: String + description: String volunteersRequired: Int } @@ -284,11 +306,11 @@ export const inputs = gql` id_starts_with: ID user: UserWhereInput - } - input MessageChatInput { - message: String! - receiver: ID! + creatorId: ID + creatorId_not: ID + creatorId_in: [ID!] + creatorId_not_in: [ID!] } input NoteInput { @@ -424,13 +446,36 @@ export const inputs = gql` tagId: ID! } + input AddPeopleToUserTagInput { + userIds: [ID!]! + tagId: ID! + } + + input TagActionsInput { + currentTagId: ID! + selectedTagIds: [ID!]! + } + + input UserTagWhereInput { + name: UserTagNameWhereInput + } + + input UserTagNameWhereInput { + starts_with: String! + } + + input UserTagSortedByInput { + id: SortedByOrder! + } + input UpdateActionItemInput { assigneeId: ID + assigneeType: String preCompletionNotes: String postCompletionNotes: String dueDate: Date completionDate: Date - allotedHours: Float + allottedHours: Float isCompleted: Boolean } @@ -600,6 +645,25 @@ export const inputs = gql` event_title_contains: String } + + input UserTagUsersAssignedToSortedByInput { + id: SortedByOrder! + } + + input UserTagUsersAssignedToWhereInput { + firstName: UserNameWhereInput + lastName: UserNameWhereInput + } + + input UserTagUsersToAssignToWhereInput { + firstName: UserNameWhereInput + lastName: UserNameWhereInput + } + + input UserNameWhereInput { + starts_with: String! + } + input PostUpdateInput { text: String title: String @@ -624,6 +688,20 @@ export const inputs = gql` file: String } + input VolunteerMembershipInput { + event: ID! + group: ID + status: String! + userId: ID! + } + + input VolunteerRankWhereInput { + nameContains: String + orderBy: String! + timeFrame: String! + limit: Int + } + input VenueWhereInput { name_contains: String name_starts_with: String diff --git a/src/typeDefs/mutations.ts b/src/typeDefs/mutations.ts index bca74770e5..5253da9783 100644 --- a/src/typeDefs/mutations.ts +++ b/src/typeDefs/mutations.ts @@ -33,18 +33,22 @@ export const mutations = gql` addUserImage(file: String!): User! @auth - addUserToGroupChat(userId: ID!, chatId: ID!): GroupChat! @auth - addUserToUserFamily(userId: ID!, familyId: ID!): UserFamily! @auth + addPeopleToUserTag(input: AddPeopleToUserTagInput!): UserTag + @auth + @role(requires: ADMIN) + + assignToUserTags(input: TagActionsInput!): UserTag + @auth + @role(requires: ADMIN) + removeUserFromUserFamily(userId: ID!, familyId: ID!): UserFamily! @auth removeUserFamily(familyId: ID!): UserFamily! @auth createUserFamily(data: createUserFamilyInput!): UserFamily! @auth - adminRemoveGroup(groupId: ID!): GroupChat! @auth - assignUserTag(input: ToggleUserTagAssignInput!): User @auth blockPluginCreationBySuperadmin( @@ -88,7 +92,7 @@ export const mutations = gql` createComment(postId: ID!, data: CommentInput!): Comment @auth - createDirectChat(data: createChatInput!): DirectChat! @auth + createChat(data: chatInput!): Chat createDonation( userId: ID! @@ -110,10 +114,6 @@ export const mutations = gql` data: FundCampaignPledgeInput! ): FundraisingCampaignPledge! @auth - createGroupChat(data: createGroupChatInput!): GroupChat! @auth - - createMessageChat(data: MessageChatInput!): MessageChat! @auth - createOrganization(data: OrganizationInput, file: String): Organization! @auth @role(requires: SUPERADMIN) @@ -139,6 +139,10 @@ export const mutations = gql` createVenue(data: VenueInput!): Venue @auth + createVolunteerMembership( + data: VolunteerMembershipInput! + ): VolunteerMembership! @auth + deleteAdvertisement(id: ID!): DeleteAdvertisementPayload deleteAgendaCategory(id: ID!): ID! @auth @@ -198,8 +202,6 @@ export const mutations = gql` removeComment(id: ID!): Comment @auth - removeDirectChat(chatId: ID!, organizationId: ID!): DirectChat! @auth - removeEvent( id: ID! recurringEventDeleteType: RecurringEventMutationType @@ -214,8 +216,6 @@ export const mutations = gql` removeEventVolunteerGroup(id: ID!): EventVolunteerGroup! @auth - removeGroupChat(chatId: ID!): GroupChat! @auth - removeMember(data: UserAndOrganizationInput!): Organization! @auth removeOrganization(id: ID!): UserData! @auth @role(requires: SUPERADMIN) @@ -234,10 +234,12 @@ export const mutations = gql` removeSampleOrganization: Boolean! @auth - removeUserFromGroupChat(userId: ID!, chatId: ID!): GroupChat! @auth - removeUserImage: User! @auth + removeFromUserTags(input: TagActionsInput!): UserTag + @auth + @role(requires: ADMIN) + resetCommunity: Boolean! @auth @role(requires: SUPERADMIN) revokeRefreshTokenForUser: Boolean! @auth @@ -246,15 +248,11 @@ export const mutations = gql` sendMembershipRequest(organizationId: ID!): MembershipRequest! @auth - sendMessageToDirectChat( - chatId: ID! - messageContent: String! - ): DirectChatMessage! @auth - - sendMessageToGroupChat( + sendMessageToChat( chatId: ID! messageContent: String! - ): GroupChatMessage! @auth + replyTo: ID + ): ChatMessage! @auth signUp(data: UserInput!, file: String): AuthData! @@ -312,9 +310,12 @@ export const mutations = gql` updateEventVolunteerGroup( id: ID! - data: UpdateEventVolunteerGroupInput + data: UpdateEventVolunteerGroupInput! ): EventVolunteerGroup! @auth + updateVolunteerMembership(id: ID!, status: String!): VolunteerMembership! + @auth + updateFundraisingCampaign( id: ID! data: UpdateFundCampaignInput! @@ -337,6 +338,8 @@ export const mutations = gql` updatePluginStatus(id: ID!, orgId: ID!): Plugin! + updateSessionTimeout(timeout: Int!): Boolean! @auth + updateUserTag(input: UpdateUserTagInput!): UserTag @auth updateUserProfile(data: UpdateUserInput, file: String): User! @auth diff --git a/src/typeDefs/queries.ts b/src/typeDefs/queries.ts index 4db8616859..3d7d5f0223 100644 --- a/src/typeDefs/queries.ts +++ b/src/typeDefs/queries.ts @@ -16,6 +16,12 @@ export const queries = gql` orderBy: ActionItemsOrderByInput ): [ActionItem] + actionItemsByUser( + userId: ID! + where: ActionItemWhereInput + orderBy: ActionItemsOrderByInput + ): [ActionItem] + actionItemCategoriesByOrganization( organizationId: ID! where: ActionItemCategoryWhereInput @@ -44,15 +50,9 @@ export const queries = gql` customDataByOrganization(organizationId: ID!): [UserCustomData!]! - directChatsByUserID(id: ID!): [DirectChat] - - directChatById(id: ID!): DirectChat - - groupChatById(id: ID!): GroupChat + chatById(id: ID!): Chat! - groupChatsByUserId(id: ID!): [GroupChat] - - directChatsMessagesByChatID(id: ID!): [DirectChatMessage] + chatsByUserId(id: ID!): [Chat] event(id: ID!): Event @@ -60,17 +60,32 @@ export const queries = gql` eventsByOrganizationConnection( where: EventWhereInput + upcomingOnly: Boolean first: Int skip: Int orderBy: EventOrderByInput ): [Event!]! - eventVolunteersByEvent(id: ID!): [EventVolunteer] + getEventVolunteers( + where: EventVolunteerWhereInput! + orderBy: EventVolunteersOrderByInput + ): [EventVolunteer]! getEventVolunteerGroups( - where: EventVolunteerGroupWhereInput + where: EventVolunteerGroupWhereInput! + orderBy: EventVolunteerGroupOrderByInput ): [EventVolunteerGroup]! + getVolunteerMembership( + where: VolunteerMembershipWhereInput! + orderBy: VolunteerMembershipOrderByInput + ): [VolunteerMembership]! + + getVolunteerRanks( + orgId: ID! + where: VolunteerRankWhereInput! + ): [VolunteerRank]! + fundsByOrganization( organizationId: ID! where: FundWhereInput @@ -130,10 +145,10 @@ export const queries = gql` getUserTag(id: ID!): UserTag - getUserTagAncestors(id: ID!): [UserTag] - getAllNotesForAgendaItem(agendaItemId: ID!): [Note] + getRecurringEvents(baseRecurringEventId: ID!): [Event] + advertisementsConnection( after: String before: String @@ -200,5 +215,7 @@ export const queries = gql` ): [UserData]! @auth venue(id: ID!): Venue + + eventsAttendedByUser(id: ID, orderBy: EventOrderByInput): [Event] } `; diff --git a/src/typeDefs/subscriptions.ts b/src/typeDefs/subscriptions.ts index 4c718b9761..f5e3c89c2b 100644 --- a/src/typeDefs/subscriptions.ts +++ b/src/typeDefs/subscriptions.ts @@ -3,9 +3,7 @@ import { gql } from "graphql-tag"; // Place fields alphabetically to ensure easier lookup and navigation. export const subscriptions = gql` type Subscription { - directMessageChat: MessageChat - messageSentToDirectChat(userId: ID!): DirectChatMessage - messageSentToGroupChat(userId: ID!): GroupChatMessage + messageSentToChat(userId: ID!): ChatMessage onPluginUpdate: Plugin } `; diff --git a/src/typeDefs/types.ts b/src/typeDefs/types.ts index 8faf1a6521..25b6f12b0f 100644 --- a/src/typeDefs/types.ts +++ b/src/typeDefs/types.ts @@ -67,15 +67,19 @@ export const types = gql` createdBy: User updatedBy: User } + # Action Item for a ActionItemCategory type ActionItem { _id: ID! - assignee: User + assignee: EventVolunteer + assigneeGroup: EventVolunteerGroup + assigneeUser: User + assigneeType: String! assigner: User actionItemCategory: ActionItemCategory preCompletionNotes: String postCompletionNotes: String - allotedHours: Float + allottedHours: Float assignmentDate: Date! dueDate: Date! completionDate: Date! @@ -130,6 +134,7 @@ export const types = gql` logoUrl: String websiteLink: String socialMediaUrls: SocialMediaUrls + timeout: Int } type CreateAdminPayload { user: AppUserProfile @@ -164,11 +169,6 @@ export const types = gql` userErrors: [CreateCommentError!]! } - type createDirectChatPayload { - directChat: DirectChat - userErrors: [CreateDirectChatError!]! - } - type DeletePayload { success: Boolean! } @@ -177,26 +177,6 @@ export const types = gql` advertisement: Advertisement } - type DirectChat { - _id: ID! - users: [User!]! - messages: [DirectChatMessage] - creator: User - createdAt: DateTime! - updatedAt: DateTime! - organization: Organization - } - - type DirectChatMessage { - _id: ID! - directChatMessageBelongsTo: DirectChat! - sender: User! - receiver: User! - createdAt: DateTime! - updatedAt: DateTime! - messageContent: String! - } - type Donation { _id: ID! userId: ID! @@ -276,21 +256,36 @@ export const types = gql` feedback: [Feedback!]! averageFeedbackScore: Float agendaItems: [AgendaItem] + volunteers: [EventVolunteer] + volunteerGroups: [EventVolunteerGroup] } type EventVolunteer { _id: ID! - createdAt: DateTime! + user: User! creator: User event: Event - group: EventVolunteerGroup - isAssigned: Boolean - isInvited: Boolean - response: String - user: User! + groups: [EventVolunteerGroup] + hasAccepted: Boolean! + isPublic: Boolean! + hoursVolunteered: Float! + assignments: [ActionItem] + hoursHistory: [HoursHistory] + createdAt: DateTime! updatedAt: DateTime! } + type HoursHistory { + hours: Float! + date: Date! + } + + type VolunteerRank { + rank: Int! + user: User! + hoursVolunteered: Float! + } + type EventAttendee { _id: ID! userId: ID! @@ -307,14 +302,28 @@ export const types = gql` type EventVolunteerGroup { _id: ID! - createdAt: DateTime! creator: User event: Event leader: User! name: String + description: String + createdAt: DateTime! updatedAt: DateTime! volunteers: [EventVolunteer] volunteersRequired: Int + assignments: [ActionItem] + } + + type VolunteerMembership { + _id: ID! + status: String! + volunteer: EventVolunteer! + event: Event! + group: EventVolunteerGroup + createdBy: User + updatedBy: User + createdAt: DateTime! + updatedAt: DateTime! } type Feedback { @@ -326,6 +335,30 @@ export const types = gql` updatedAt: DateTime! } + type File { + _id: ID! + fileName: String! + mimeType: String! + size: Int! + hash: Hash! + uri: String! + referenceCount: Int! + metadata: FileMetadata! + encryption: Boolean! + archived: Boolean! + visibility: FileVisibility! + backupStatus: String! + status: Status! + createdAt: DateTime! + updatedAt: DateTime! + archivedAt: DateTime + } + + type FileMetadata { + objectKey: String! + bucketName: String! + } + type Fund { _id: ID! organizationId: ID! @@ -372,24 +405,9 @@ export const types = gql` admins: [User!]! } - type GroupChat { - _id: ID! - title: String! - users: [User!]! - messages: [GroupChatMessage] - creator: User - createdAt: DateTime! - updatedAt: DateTime! - organization: Organization! - } - - type GroupChatMessage { - _id: ID! - groupChatMessageBelongsTo: GroupChat! - sender: User! - createdAt: DateTime! - updatedAt: DateTime! - messageContent: String! + type Hash { + value: String! + algorithm: String! } type Language { @@ -423,16 +441,6 @@ export const types = gql` creator: User } - type MessageChat { - _id: ID! - sender: User! - receiver: User! - message: String! - languageBarrier: Boolean - createdAt: DateTime! - updatedAt: DateTime! - } - type Note { _id: ID! content: String! @@ -477,6 +485,8 @@ export const types = gql` before: String first: PositiveInt last: PositiveInt + where: UserTagWhereInput + sortedBy: UserTagSortedByInput ): UserTagsConnection posts( after: String @@ -563,8 +573,7 @@ export const types = gql` createdAt: DateTime! creator: User updatedAt: DateTime! - imageUrl: URL - videoUrl: URL + file: File organization: Organization! likedBy: [User] comments: [Comment] @@ -642,6 +651,7 @@ export const types = gql` firstName: String! gender: Gender image: String + file: File joinedOrganizations: [Organization] lastName: String! maritalStatus: MaritalStatus @@ -649,6 +659,7 @@ export const types = gql` phone: UserPhone membershipRequests: [MembershipRequest] registeredEvents: [Event] + eventsAttended: [Event] pluginCreationAllowed: Boolean! tagsAssignedWith( after: String @@ -717,6 +728,10 @@ export const types = gql` """ parentTag: UserTag """ + A field to traverse the ancestor tags of this UserTag. + """ + ancestorTags: [UserTag] + """ A connection field to traverse a list of UserTag this UserTag is a parent to. """ @@ -725,6 +740,8 @@ export const types = gql` before: String first: PositiveInt last: PositiveInt + where: UserTagWhereInput + sortedBy: UserTagSortedByInput ): UserTagsConnection """ A connection field to traverse a list of User this UserTag is assigned @@ -735,6 +752,20 @@ export const types = gql` before: String first: PositiveInt last: PositiveInt + where: UserTagUsersAssignedToWhereInput + sortedBy: UserTagUsersAssignedToSortedByInput + ): UsersConnection + + """ + A connection field to traverse a list of Users this UserTag is not assigned + to, to see and select among them and assign this tag. + """ + usersToAssignTo( + after: String + before: String + first: PositiveInt + last: PositiveInt + where: UserTagUsersToAssignToWhereInput ): UsersConnection } @@ -771,4 +802,30 @@ export const types = gql` cursor: String! node: User! } + + type Chat { + _id: ID! + isGroup: Boolean! + name: String + createdAt: DateTime! + creator: User + messages: [ChatMessage] + organization: Organization + updatedAt: DateTime! + users: [User!]! + admins: [User] + lastMessageId: String + image: String + } + + type ChatMessage { + _id: ID! + createdAt: DateTime! + chatMessageBelongsTo: Chat! + replyTo: ChatMessage + messageContent: String! + sender: User! + deletedBy: [User] + updatedAt: DateTime! + } `; diff --git a/src/types/generatedGraphQLTypes.ts b/src/types/generatedGraphQLTypes.ts index 0f4178071b..f3421b206c 100644 --- a/src/types/generatedGraphQLTypes.ts +++ b/src/types/generatedGraphQLTypes.ts @@ -7,11 +7,10 @@ import type { InterfaceAdvertisement as InterfaceAdvertisementModel } from '../m import type { InterfaceAgendaItem as InterfaceAgendaItemModel } from '../models/AgendaItem'; import type { InterfaceAgendaSection as InterfaceAgendaSectionModel } from '../models/AgendaSection'; import type { InterfaceCheckIn as InterfaceCheckInModel } from '../models/CheckIn'; -import type { InterfaceMessageChat as InterfaceMessageChatModel } from '../models/MessageChat'; import type { InterfaceComment as InterfaceCommentModel } from '../models/Comment'; import type { InterfaceCommunity as InterfaceCommunityModel } from '../models/Community'; -import type { InterfaceDirectChat as InterfaceDirectChatModel } from '../models/DirectChat'; -import type { InterfaceDirectChatMessage as InterfaceDirectChatMessageModel } from '../models/DirectChatMessage'; +import type { InterfaceChat as InterfaceChatModel } from '../models/Chat'; +import type { InterfaceChatMessage as InterfaceChatMessageModel } from '../models/ChatMessage'; import type { InterfaceDonation as InterfaceDonationModel } from '../models/Donation'; import type { InterfaceEvent as InterfaceEventModel } from '../models/Event'; import type { InterfaceEventAttendee as InterfaceEventAttendeeModel } from '../models/EventAttendee'; @@ -23,8 +22,6 @@ import type { InterfaceFund as InterfaceFundModel } from '../models/Fund'; import type { InterfaceFundraisingCampaign as InterfaceFundraisingCampaignModel } from '../models/FundraisingCampaign'; import type { InterfaceFundraisingCampaignPledges as InterfaceFundraisingCampaignPledgesModel } from '../models/FundraisingCampaignPledge'; import type { InterfaceGroup as InterfaceGroupModel } from '../models/Group'; -import type { InterfaceGroupChat as InterfaceGroupChatModel } from '../models/GroupChat'; -import type { InterfaceGroupChatMessage as InterfaceGroupChatMessageModel } from '../models/GroupChatMessage'; import type { InterfaceLanguage as InterfaceLanguageModel } from '../models/Language'; import type { InterfaceMembershipRequest as InterfaceMembershipRequestModel } from '../models/MembershipRequest'; import type { InterfaceMessage as InterfaceMessageModel } from '../models/Message'; @@ -37,6 +34,7 @@ import type { InterfaceRecurrenceRule as InterfaceRecurrenceRuleModel } from '.. import type { InterfaceOrganizationTagUser as InterfaceOrganizationTagUserModel } from '../models/OrganizationTagUser'; import type { InterfaceUser as InterfaceUserModel } from '../models/User'; import type { InterfaceVenue as InterfaceVenueModel } from '../models/Venue'; +import type { InterfaceVolunteerMembership as InterfaceVolunteerMembershipModel } from '../models/VolunteerMembership'; export type Maybe = T | null; export type InputMaybe = Maybe; export type Exact = { [K in keyof T]: T[K] }; @@ -72,8 +70,11 @@ export type ActionItem = { __typename?: 'ActionItem'; _id: Scalars['ID']['output']; actionItemCategory?: Maybe; - allotedHours?: Maybe; - assignee?: Maybe; + allottedHours?: Maybe; + assignee?: Maybe; + assigneeGroup?: Maybe; + assigneeType: Scalars['String']['output']; + assigneeUser?: Maybe; assigner?: Maybe; assignmentDate: Scalars['Date']['output']; completionDate: Scalars['Date']['output']; @@ -109,6 +110,7 @@ export type ActionItemWhereInput = { categoryName?: InputMaybe; event_id?: InputMaybe; is_completed?: InputMaybe; + orgId?: InputMaybe; }; export type ActionItemsOrderByInput = @@ -117,6 +119,11 @@ export type ActionItemsOrderByInput = | 'dueDate_ASC' | 'dueDate_DESC'; +export type AddPeopleToUserTagInput = { + tagId: Scalars['ID']['input']; + userIds: Array; +}; + export type Address = { __typename?: 'Address'; city?: Maybe; @@ -264,6 +271,34 @@ export type CampaignWhereInput = { organizationId?: InputMaybe; }; +export type Chat = { + __typename?: 'Chat'; + _id: Scalars['ID']['output']; + admins?: Maybe>>; + createdAt: Scalars['DateTime']['output']; + creator?: Maybe; + image?: Maybe; + isGroup: Scalars['Boolean']['output']; + lastMessageId?: Maybe; + messages?: Maybe>>; + name?: Maybe; + organization?: Maybe; + updatedAt: Scalars['DateTime']['output']; + users: Array; +}; + +export type ChatMessage = { + __typename?: 'ChatMessage'; + _id: Scalars['ID']['output']; + chatMessageBelongsTo: Chat; + createdAt: Scalars['DateTime']['output']; + deletedBy?: Maybe>>; + messageContent: Scalars['String']['output']; + replyTo?: Maybe; + sender: User; + updatedAt: Scalars['DateTime']['output']; +}; + export type CheckIn = { __typename?: 'CheckIn'; _id: Scalars['ID']['output']; @@ -318,6 +353,7 @@ export type Community = { logoUrl?: Maybe; name: Scalars['String']['output']; socialMediaUrls?: Maybe; + timeout?: Maybe; websiteLink?: Maybe; }; @@ -352,8 +388,9 @@ export type ConnectionPageInfo = { }; export type CreateActionItemInput = { - allotedHours?: InputMaybe; + allottedHours?: InputMaybe; assigneeId: Scalars['ID']['input']; + assigneeType: Scalars['String']['input']; dueDate?: InputMaybe; eventId?: InputMaybe; preCompletionNotes?: InputMaybe; @@ -415,8 +452,6 @@ export type CreateCommentPayload = { userErrors: Array; }; -export type CreateDirectChatError = OrganizationNotFoundError | UserNotFoundError; - export type CreateMemberError = MemberNotFoundError | OrganizationNotFoundError | UserNotAuthorizedAdminError | UserNotAuthorizedError | UserNotFoundError; export type CreateMemberPayload = { @@ -625,28 +660,6 @@ export type DeletePayload = { success: Scalars['Boolean']['output']; }; -export type DirectChat = { - __typename?: 'DirectChat'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - creator?: Maybe; - messages?: Maybe>>; - organization?: Maybe; - updatedAt: Scalars['DateTime']['output']; - users: Array; -}; - -export type DirectChatMessage = { - __typename?: 'DirectChatMessage'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - directChatMessageBelongsTo: DirectChat; - messageContent: Scalars['String']['output']; - receiver: User; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - export type Donation = { __typename?: 'Donation'; _id: Scalars['ID']['output']; @@ -741,6 +754,8 @@ export type Event = { startTime?: Maybe; title: Scalars['String']['output']; updatedAt: Scalars['DateTime']['output']; + volunteerGroups?: Maybe>>; + volunteers?: Maybe>>; }; @@ -811,13 +826,15 @@ export type EventOrderByInput = export type EventVolunteer = { __typename?: 'EventVolunteer'; _id: Scalars['ID']['output']; + assignments?: Maybe>>; createdAt: Scalars['DateTime']['output']; creator?: Maybe; event?: Maybe; - group?: Maybe; - isAssigned?: Maybe; - isInvited?: Maybe; - response?: Maybe; + groups?: Maybe>>; + hasAccepted: Scalars['Boolean']['output']; + hoursHistory?: Maybe>>; + hoursVolunteered: Scalars['Float']['output']; + isPublic: Scalars['Boolean']['output']; updatedAt: Scalars['DateTime']['output']; user: User; }; @@ -825,8 +842,10 @@ export type EventVolunteer = { export type EventVolunteerGroup = { __typename?: 'EventVolunteerGroup'; _id: Scalars['ID']['output']; + assignments?: Maybe>>; createdAt: Scalars['DateTime']['output']; creator?: Maybe; + description?: Maybe; event?: Maybe; leader: User; name?: Maybe; @@ -836,20 +855,31 @@ export type EventVolunteerGroup = { }; export type EventVolunteerGroupInput = { + description?: InputMaybe; eventId: Scalars['ID']['input']; - name?: InputMaybe; + leaderId: Scalars['ID']['input']; + name: Scalars['String']['input']; + volunteerUserIds: Array; volunteersRequired?: InputMaybe; }; +export type EventVolunteerGroupOrderByInput = + | 'assignments_ASC' + | 'assignments_DESC' + | 'volunteers_ASC' + | 'volunteers_DESC'; + export type EventVolunteerGroupWhereInput = { eventId?: InputMaybe; + leaderName?: InputMaybe; name_contains?: InputMaybe; - volunteerId?: InputMaybe; + orgId?: InputMaybe; + userId?: InputMaybe; }; export type EventVolunteerInput = { eventId: Scalars['ID']['input']; - groupId: Scalars['ID']['input']; + groupId?: InputMaybe; userId: Scalars['ID']['input']; }; @@ -857,6 +887,18 @@ export type EventVolunteerResponse = | 'NO' | 'YES'; +export type EventVolunteerWhereInput = { + eventId?: InputMaybe; + groupId?: InputMaybe; + hasAccepted?: InputMaybe; + id?: InputMaybe; + name_contains?: InputMaybe; +}; + +export type EventVolunteersOrderByInput = + | 'hoursVolunteered_ASC' + | 'hoursVolunteered_DESC'; + export type EventWhereInput = { description?: InputMaybe; description_contains?: InputMaybe; @@ -912,6 +954,36 @@ export type FieldError = { path: Array; }; +export type File = { + __typename?: 'File'; + _id: Scalars['ID']['output']; + archived: Scalars['Boolean']['output']; + archivedAt?: Maybe; + backupStatus: Scalars['String']['output']; + createdAt: Scalars['DateTime']['output']; + encryption: Scalars['Boolean']['output']; + fileName: Scalars['String']['output']; + hash: Hash; + metadata: FileMetadata; + mimeType: Scalars['String']['output']; + referenceCount: Scalars['Int']['output']; + size: Scalars['Int']['output']; + status: Status; + updatedAt: Scalars['DateTime']['output']; + uri: Scalars['String']['output']; + visibility: FileVisibility; +}; + +export type FileMetadata = { + __typename?: 'FileMetadata'; + bucketName: Scalars['String']['output']; + objectKey: Scalars['String']['output']; +}; + +export type FileVisibility = + | 'PRIVATE' + | 'PUBLIC'; + export type ForgotPasswordData = { newPassword: Scalars['String']['input']; otpToken: Scalars['String']['input']; @@ -1017,26 +1089,16 @@ export type Group = { updatedAt: Scalars['DateTime']['output']; }; -export type GroupChat = { - __typename?: 'GroupChat'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - creator?: Maybe; - messages?: Maybe>>; - organization: Organization; - title: Scalars['String']['output']; - updatedAt: Scalars['DateTime']['output']; - users: Array; +export type Hash = { + __typename?: 'Hash'; + algorithm: Scalars['String']['output']; + value: Scalars['String']['output']; }; -export type GroupChatMessage = { - __typename?: 'GroupChatMessage'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - groupChatMessageBelongsTo: GroupChat; - messageContent: Scalars['String']['output']; - sender: User; - updatedAt: Scalars['DateTime']['output']; +export type HoursHistory = { + __typename?: 'HoursHistory'; + date: Scalars['Date']['output']; + hours: Scalars['Float']['output']; }; export type InvalidCursor = FieldError & { @@ -1111,6 +1173,10 @@ export type MembershipRequest = { }; export type MembershipRequestsWhereInput = { + creatorId?: InputMaybe; + creatorId_in?: InputMaybe>; + creatorId_not?: InputMaybe; + creatorId_not_in?: InputMaybe>; id?: InputMaybe; id_contains?: InputMaybe; id_in?: InputMaybe>; @@ -1131,22 +1197,6 @@ export type Message = { videoUrl?: Maybe; }; -export type MessageChat = { - __typename?: 'MessageChat'; - _id: Scalars['ID']['output']; - createdAt: Scalars['DateTime']['output']; - languageBarrier?: Maybe; - message: Scalars['String']['output']; - receiver: User; - sender: User; - updatedAt: Scalars['DateTime']['output']; -}; - -export type MessageChatInput = { - message: Scalars['String']['input']; - receiver: Scalars['ID']['input']; -}; - export type MinimumLengthError = FieldError & { __typename?: 'MinimumLengthError'; limit: Scalars['Int']['output']; @@ -1168,12 +1218,12 @@ export type Mutation = { addLanguageTranslation: Language; addOrganizationCustomField: OrganizationCustomField; addOrganizationImage: Organization; + addPeopleToUserTag?: Maybe; addPledgeToFundraisingCampaign: FundraisingCampaignPledge; addUserCustomData: UserCustomData; addUserImage: User; - addUserToGroupChat: GroupChat; addUserToUserFamily: UserFamily; - adminRemoveGroup: GroupChat; + assignToUserTags?: Maybe; assignUserTag?: Maybe; blockPluginCreationBySuperadmin: AppUserProfile; blockUser: User; @@ -1187,8 +1237,8 @@ export type Mutation = { createAgendaCategory: AgendaCategory; createAgendaItem: AgendaItem; createAgendaSection: AgendaSection; + createChat?: Maybe; createComment?: Maybe; - createDirectChat: DirectChat; createDonation: Donation; createEvent: Event; createEventVolunteer: EventVolunteer; @@ -1196,9 +1246,7 @@ export type Mutation = { createFund: Fund; createFundraisingCampaign: FundraisingCampaign; createFundraisingCampaignPledge: FundraisingCampaignPledge; - createGroupChat: GroupChat; createMember: CreateMemberPayload; - createMessageChat: MessageChat; createNote: Note; createOrganization: Organization; createPlugin: Plugin; @@ -1207,6 +1255,7 @@ export type Mutation = { createUserFamily: UserFamily; createUserTag?: Maybe; createVenue?: Maybe; + createVolunteerMembership: VolunteerMembership; deleteAdvertisement?: Maybe; deleteAgendaCategory: Scalars['ID']['output']; deleteDonationById: DeletePayload; @@ -1233,13 +1282,12 @@ export type Mutation = { removeAgendaItem: AgendaItem; removeAgendaSection: Scalars['ID']['output']; removeComment?: Maybe; - removeDirectChat: DirectChat; removeEvent: Event; removeEventAttendee: User; removeEventVolunteer: EventVolunteer; removeEventVolunteerGroup: EventVolunteerGroup; + removeFromUserTags?: Maybe; removeFundraisingCampaignPledge: FundraisingCampaignPledge; - removeGroupChat: GroupChat; removeMember: Organization; removeOrganization: UserData; removeOrganizationCustomField: OrganizationCustomField; @@ -1248,7 +1296,6 @@ export type Mutation = { removeSampleOrganization: Scalars['Boolean']['output']; removeUserCustomData: UserCustomData; removeUserFamily: UserFamily; - removeUserFromGroupChat: GroupChat; removeUserFromUserFamily: UserFamily; removeUserImage: User; removeUserTag?: Maybe; @@ -1256,8 +1303,7 @@ export type Mutation = { revokeRefreshTokenForUser: Scalars['Boolean']['output']; saveFcmToken: Scalars['Boolean']['output']; sendMembershipRequest: MembershipRequest; - sendMessageToDirectChat: DirectChatMessage; - sendMessageToGroupChat: GroupChatMessage; + sendMessageToChat: ChatMessage; signUp: AuthData; togglePostPin: Post; unassignUserTag?: Maybe; @@ -1283,10 +1329,12 @@ export type Mutation = { updateOrganization: Organization; updatePluginStatus: Plugin; updatePost: Post; + updateSessionTimeout: Scalars['Boolean']['output']; updateUserPassword: UserData; updateUserProfile: User; updateUserRoleInOrganization: Organization; updateUserTag?: Maybe; + updateVolunteerMembership: VolunteerMembership; }; @@ -1323,6 +1371,11 @@ export type MutationAddOrganizationImageArgs = { }; +export type MutationAddPeopleToUserTagArgs = { + input: AddPeopleToUserTagInput; +}; + + export type MutationAddPledgeToFundraisingCampaignArgs = { campaignId: Scalars['ID']['input']; pledgeId: Scalars['ID']['input']; @@ -1341,20 +1394,14 @@ export type MutationAddUserImageArgs = { }; -export type MutationAddUserToGroupChatArgs = { - chatId: Scalars['ID']['input']; - userId: Scalars['ID']['input']; -}; - - export type MutationAddUserToUserFamilyArgs = { familyId: Scalars['ID']['input']; userId: Scalars['ID']['input']; }; -export type MutationAdminRemoveGroupArgs = { - groupId: Scalars['ID']['input']; +export type MutationAssignToUserTagsArgs = { + input: TagActionsInput; }; @@ -1428,14 +1475,14 @@ export type MutationCreateAgendaSectionArgs = { }; -export type MutationCreateCommentArgs = { - data: CommentInput; - postId: Scalars['ID']['input']; +export type MutationCreateChatArgs = { + data: ChatInput; }; -export type MutationCreateDirectChatArgs = { - data: CreateChatInput; +export type MutationCreateCommentArgs = { + data: CommentInput; + postId: Scalars['ID']['input']; }; @@ -1480,21 +1527,11 @@ export type MutationCreateFundraisingCampaignPledgeArgs = { }; -export type MutationCreateGroupChatArgs = { - data: CreateGroupChatInput; -}; - - export type MutationCreateMemberArgs = { input: UserAndOrganizationInput; }; -export type MutationCreateMessageChatArgs = { - data: MessageChatInput; -}; - - export type MutationCreateNoteArgs = { data: NoteInput; }; @@ -1535,6 +1572,11 @@ export type MutationCreateVenueArgs = { }; +export type MutationCreateVolunteerMembershipArgs = { + data: VolunteerMembershipInput; +}; + + export type MutationDeleteAdvertisementArgs = { id: Scalars['ID']['input']; }; @@ -1660,12 +1702,6 @@ export type MutationRemoveCommentArgs = { }; -export type MutationRemoveDirectChatArgs = { - chatId: Scalars['ID']['input']; - organizationId: Scalars['ID']['input']; -}; - - export type MutationRemoveEventArgs = { id: Scalars['ID']['input']; recurringEventDeleteType?: InputMaybe; @@ -1687,13 +1723,13 @@ export type MutationRemoveEventVolunteerGroupArgs = { }; -export type MutationRemoveFundraisingCampaignPledgeArgs = { - id: Scalars['ID']['input']; +export type MutationRemoveFromUserTagsArgs = { + input: TagActionsInput; }; -export type MutationRemoveGroupChatArgs = { - chatId: Scalars['ID']['input']; +export type MutationRemoveFundraisingCampaignPledgeArgs = { + id: Scalars['ID']['input']; }; @@ -1733,12 +1769,6 @@ export type MutationRemoveUserFamilyArgs = { }; -export type MutationRemoveUserFromGroupChatArgs = { - chatId: Scalars['ID']['input']; - userId: Scalars['ID']['input']; -}; - - export type MutationRemoveUserFromUserFamilyArgs = { familyId: Scalars['ID']['input']; userId: Scalars['ID']['input']; @@ -1760,15 +1790,10 @@ export type MutationSendMembershipRequestArgs = { }; -export type MutationSendMessageToDirectChatArgs = { - chatId: Scalars['ID']['input']; - messageContent: Scalars['String']['input']; -}; - - -export type MutationSendMessageToGroupChatArgs = { +export type MutationSendMessageToChatArgs = { chatId: Scalars['ID']['input']; messageContent: Scalars['String']['input']; + replyTo?: InputMaybe; }; @@ -1865,7 +1890,7 @@ export type MutationUpdateEventVolunteerArgs = { export type MutationUpdateEventVolunteerGroupArgs = { - data?: InputMaybe; + data: UpdateEventVolunteerGroupInput; id: Scalars['ID']['input']; }; @@ -1918,6 +1943,11 @@ export type MutationUpdatePostArgs = { }; +export type MutationUpdateSessionTimeoutArgs = { + timeout: Scalars['Int']['input']; +}; + + export type MutationUpdateUserPasswordArgs = { data: UpdateUserPasswordInput; }; @@ -1940,6 +1970,12 @@ export type MutationUpdateUserTagArgs = { input: UpdateUserTagInput; }; + +export type MutationUpdateVolunteerMembershipArgs = { + id: Scalars['ID']['input']; + status: Scalars['String']['input']; +}; + export type Note = { __typename?: 'Note'; _id: Scalars['ID']['output']; @@ -2022,6 +2058,8 @@ export type OrganizationUserTagsArgs = { before?: InputMaybe; first?: InputMaybe; last?: InputMaybe; + sortedBy?: InputMaybe; + where?: InputMaybe; }; export type OrganizationCustomField = { @@ -2180,7 +2218,7 @@ export type Post = { comments?: Maybe>>; createdAt: Scalars['DateTime']['output']; creator?: Maybe; - imageUrl?: Maybe; + file?: Maybe; likeCount?: Maybe; likedBy?: Maybe>>; organization: Organization; @@ -2188,7 +2226,6 @@ export type Post = { text: Scalars['String']['output']; title?: Maybe; updatedAt: Scalars['DateTime']['output']; - videoUrl?: Maybe; }; export type PostEdge = { @@ -2270,20 +2307,20 @@ export type Query = { actionItemCategoriesByOrganization?: Maybe>>; actionItemsByEvent?: Maybe>>; actionItemsByOrganization?: Maybe>>; + actionItemsByUser?: Maybe>>; adminPlugin?: Maybe>>; advertisementsConnection?: Maybe; agendaCategory: AgendaCategory; agendaItemByEvent?: Maybe>>; agendaItemByOrganization?: Maybe>>; agendaItemCategoriesByOrganization?: Maybe>>; + chatById: Chat; + chatsByUserId?: Maybe>>; checkAuth: User; customDataByOrganization: Array; customFieldsByOrganization?: Maybe>>; - directChatById?: Maybe; - directChatsByUserID?: Maybe>>; - directChatsMessagesByChatID?: Maybe>>; event?: Maybe; - eventVolunteersByEvent?: Maybe>>; + eventsAttendedByUser?: Maybe>>; eventsByOrganization?: Maybe>>; eventsByOrganizationConnection: Array; fundsByOrganization?: Maybe>>; @@ -2299,18 +2336,19 @@ export type Query = { getEventAttendeesByEventId?: Maybe>>; getEventInvitesByUserId: Array; getEventVolunteerGroups: Array>; + getEventVolunteers: Array>; getFundById: Fund; getFundraisingCampaignPledgeById: FundraisingCampaignPledge; getFundraisingCampaigns: Array>; getNoteById: Note; getPledgesByUserId?: Maybe>>; getPlugins?: Maybe>>; + getRecurringEvents?: Maybe>>; getUserTag?: Maybe; - getUserTagAncestors?: Maybe>>; getVenueByOrgId?: Maybe>>; + getVolunteerMembership: Array>; + getVolunteerRanks: Array>; getlanguage?: Maybe>>; - groupChatById?: Maybe; - groupChatsByUserId?: Maybe>>; hasSubmittedFeedback?: Maybe; isSampleOrganization: Scalars['Boolean']['output']; joinedOrganizations?: Maybe>>; @@ -2351,6 +2389,13 @@ export type QueryActionItemsByOrganizationArgs = { }; +export type QueryActionItemsByUserArgs = { + orderBy?: InputMaybe; + userId: Scalars['ID']['input']; + where?: InputMaybe; +}; + + export type QueryAdminPluginArgs = { orgId: Scalars['ID']['input']; }; @@ -2384,27 +2429,22 @@ export type QueryAgendaItemCategoriesByOrganizationArgs = { }; -export type QueryCustomDataByOrganizationArgs = { - organizationId: Scalars['ID']['input']; -}; - - -export type QueryCustomFieldsByOrganizationArgs = { +export type QueryChatByIdArgs = { id: Scalars['ID']['input']; }; -export type QueryDirectChatByIdArgs = { +export type QueryChatsByUserIdArgs = { id: Scalars['ID']['input']; }; -export type QueryDirectChatsByUserIdArgs = { - id: Scalars['ID']['input']; +export type QueryCustomDataByOrganizationArgs = { + organizationId: Scalars['ID']['input']; }; -export type QueryDirectChatsMessagesByChatIdArgs = { +export type QueryCustomFieldsByOrganizationArgs = { id: Scalars['ID']['input']; }; @@ -2414,8 +2454,9 @@ export type QueryEventArgs = { }; -export type QueryEventVolunteersByEventArgs = { - id: Scalars['ID']['input']; +export type QueryEventsAttendedByUserArgs = { + id?: InputMaybe; + orderBy?: InputMaybe; }; @@ -2429,6 +2470,7 @@ export type QueryEventsByOrganizationConnectionArgs = { first?: InputMaybe; orderBy?: InputMaybe; skip?: InputMaybe; + upcomingOnly?: InputMaybe; where?: InputMaybe; }; @@ -2490,7 +2532,14 @@ export type QueryGetEventInvitesByUserIdArgs = { export type QueryGetEventVolunteerGroupsArgs = { - where?: InputMaybe; + orderBy?: InputMaybe; + where: EventVolunteerGroupWhereInput; +}; + + +export type QueryGetEventVolunteersArgs = { + orderBy?: InputMaybe; + where: EventVolunteerWhereInput; }; @@ -2525,12 +2574,12 @@ export type QueryGetPledgesByUserIdArgs = { }; -export type QueryGetUserTagArgs = { - id: Scalars['ID']['input']; +export type QueryGetRecurringEventsArgs = { + baseRecurringEventId: Scalars['ID']['input']; }; -export type QueryGetUserTagAncestorsArgs = { +export type QueryGetUserTagArgs = { id: Scalars['ID']['input']; }; @@ -2544,18 +2593,20 @@ export type QueryGetVenueByOrgIdArgs = { }; -export type QueryGetlanguageArgs = { - lang_code: Scalars['String']['input']; +export type QueryGetVolunteerMembershipArgs = { + orderBy?: InputMaybe; + where: VolunteerMembershipWhereInput; }; -export type QueryGroupChatByIdArgs = { - id: Scalars['ID']['input']; +export type QueryGetVolunteerRanksArgs = { + orgId: Scalars['ID']['input']; + where: VolunteerRankWhereInput; }; -export type QueryGroupChatsByUserIdArgs = { - id: Scalars['ID']['input']; +export type QueryGetlanguageArgs = { + lang_code: Scalars['String']['input']; }; @@ -2732,20 +2783,18 @@ export type Status = export type Subscription = { __typename?: 'Subscription'; - directMessageChat?: Maybe; - messageSentToDirectChat?: Maybe; - messageSentToGroupChat?: Maybe; + messageSentToChat?: Maybe; onPluginUpdate?: Maybe; }; -export type SubscriptionMessageSentToDirectChatArgs = { +export type SubscriptionMessageSentToChatArgs = { userId: Scalars['ID']['input']; }; - -export type SubscriptionMessageSentToGroupChatArgs = { - userId: Scalars['ID']['input']; +export type TagActionsInput = { + currentTagId: Scalars['ID']['input']; + selectedTagIds: Array; }; export type ToggleUserTagAssignInput = { @@ -2781,8 +2830,9 @@ export type UpdateActionItemCategoryInput = { }; export type UpdateActionItemInput = { - allotedHours?: InputMaybe; + allottedHours?: InputMaybe; assigneeId?: InputMaybe; + assigneeType?: InputMaybe; completionDate?: InputMaybe; dueDate?: InputMaybe; isCompleted?: InputMaybe; @@ -2853,16 +2903,16 @@ export type UpdateEventInput = { }; export type UpdateEventVolunteerGroupInput = { - eventId?: InputMaybe; + description?: InputMaybe; + eventId: Scalars['ID']['input']; name?: InputMaybe; volunteersRequired?: InputMaybe; }; export type UpdateEventVolunteerInput = { - eventId?: InputMaybe; - isAssigned?: InputMaybe; - isInvited?: InputMaybe; - response?: InputMaybe; + assignments?: InputMaybe>>; + hasAccepted?: InputMaybe; + isPublic?: InputMaybe; }; export type UpdateFundCampaignInput = { @@ -2939,6 +2989,8 @@ export type User = { email: Scalars['EmailAddress']['output']; employmentStatus?: Maybe; eventAdmin?: Maybe>>; + eventsAttended?: Maybe>>; + file?: Maybe; firstName: Scalars['String']['output']; gender?: Maybe; identifier: Scalars['Int']['output']; @@ -3017,6 +3069,10 @@ export type UserInput = { selectedOrganization: Scalars['ID']['input']; }; +export type UserNameWhereInput = { + starts_with: Scalars['String']['input']; +}; + export type UserNotAuthorizedAdminError = Error & { __typename?: 'UserNotAuthorizedAdminError'; message: Scalars['String']['output']; @@ -3061,6 +3117,8 @@ export type UserTag = { __typename?: 'UserTag'; /** A field to get the mongodb object id identifier for this UserTag. */ _id: Scalars['ID']['output']; + /** A field to traverse the ancestor tags of this UserTag. */ + ancestorTags?: Maybe>>; /** * A connection field to traverse a list of UserTag this UserTag is a * parent to. @@ -3077,6 +3135,11 @@ export type UserTag = { * to. */ usersAssignedTo?: Maybe; + /** + * A connection field to traverse a list of Users this UserTag is not assigned + * to, to see and select among them and assign this tag. + */ + usersToAssignTo?: Maybe; }; @@ -3085,6 +3148,8 @@ export type UserTagChildTagsArgs = { before?: InputMaybe; first?: InputMaybe; last?: InputMaybe; + sortedBy?: InputMaybe; + where?: InputMaybe; }; @@ -3093,6 +3158,43 @@ export type UserTagUsersAssignedToArgs = { before?: InputMaybe; first?: InputMaybe; last?: InputMaybe; + sortedBy?: InputMaybe; + where?: InputMaybe; +}; + + +export type UserTagUsersToAssignToArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + where?: InputMaybe; +}; + +export type UserTagNameWhereInput = { + starts_with: Scalars['String']['input']; +}; + +export type UserTagSortedByInput = { + id: SortedByOrder; +}; + +export type UserTagUsersAssignedToSortedByInput = { + id: SortedByOrder; +}; + +export type UserTagUsersAssignedToWhereInput = { + firstName?: InputMaybe; + lastName?: InputMaybe; +}; + +export type UserTagUsersToAssignToWhereInput = { + firstName?: InputMaybe; + lastName?: InputMaybe; +}; + +export type UserTagWhereInput = { + name?: InputMaybe; }; /** A default connection on the UserTag type. */ @@ -3188,6 +3290,54 @@ export type VenueWhereInput = { name_starts_with?: InputMaybe; }; +export type VolunteerMembership = { + __typename?: 'VolunteerMembership'; + _id: Scalars['ID']['output']; + createdAt: Scalars['DateTime']['output']; + createdBy?: Maybe; + event: Event; + group?: Maybe; + status: Scalars['String']['output']; + updatedAt: Scalars['DateTime']['output']; + updatedBy?: Maybe; + volunteer: EventVolunteer; +}; + +export type VolunteerMembershipInput = { + event: Scalars['ID']['input']; + group?: InputMaybe; + status: Scalars['String']['input']; + userId: Scalars['ID']['input']; +}; + +export type VolunteerMembershipOrderByInput = + | 'createdAt_ASC' + | 'createdAt_DESC'; + +export type VolunteerMembershipWhereInput = { + eventId?: InputMaybe; + eventTitle?: InputMaybe; + filter?: InputMaybe; + groupId?: InputMaybe; + status?: InputMaybe; + userId?: InputMaybe; + userName?: InputMaybe; +}; + +export type VolunteerRank = { + __typename?: 'VolunteerRank'; + hoursVolunteered: Scalars['Float']['output']; + rank: Scalars['Int']['output']; + user: User; +}; + +export type VolunteerRankWhereInput = { + limit?: InputMaybe; + nameContains?: InputMaybe; + orderBy: Scalars['String']['input']; + timeFrame: Scalars['String']['input']; +}; + export type WeekDays = | 'FRIDAY' | 'MONDAY' @@ -3197,23 +3347,14 @@ export type WeekDays = | 'TUESDAY' | 'WEDNESDAY'; -export type CreateChatInput = { +export type ChatInput = { + image?: InputMaybe; + isGroup: Scalars['Boolean']['input']; + name?: InputMaybe; organizationId?: InputMaybe; userIds: Array; }; -export type CreateDirectChatPayload = { - __typename?: 'createDirectChatPayload'; - directChat?: Maybe; - userErrors: Array; -}; - -export type CreateGroupChatInput = { - organizationId: Scalars['ID']['input']; - title: Scalars['String']['input']; - userIds: Array; -}; - export type CreateUserFamilyInput = { title: Scalars['String']['input']; userIds: Array; @@ -3287,7 +3428,6 @@ export type ResolversUnionTypes<_RefType extends Record> = { ConnectionError: ( InvalidCursor ) | ( MaximumValueError ); CreateAdminError: ( OrganizationMemberNotFoundError ) | ( OrganizationNotFoundError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); CreateCommentError: ( PostNotFoundError ); - CreateDirectChatError: ( OrganizationNotFoundError ) | ( UserNotFoundError ); CreateMemberError: ( MemberNotFoundError ) | ( OrganizationNotFoundError ) | ( UserNotAuthorizedAdminError ) | ( UserNotAuthorizedError ) | ( UserNotFoundError ); }; @@ -3305,6 +3445,7 @@ export type ResolversTypes = { ActionItemCategoryWhereInput: ActionItemCategoryWhereInput; ActionItemWhereInput: ActionItemWhereInput; ActionItemsOrderByInput: ActionItemsOrderByInput; + AddPeopleToUserTagInput: AddPeopleToUserTagInput; Address: ResolverTypeWrapper

; AddressInput: AddressInput; Advertisement: ResolverTypeWrapper; @@ -3322,6 +3463,8 @@ export type ResolversTypes = { Boolean: ResolverTypeWrapper; CampaignOrderByInput: CampaignOrderByInput; CampaignWhereInput: CampaignWhereInput; + Chat: ResolverTypeWrapper; + ChatMessage: ResolverTypeWrapper; CheckIn: ResolverTypeWrapper; CheckInCheckOutInput: CheckInCheckOutInput; CheckInStatus: ResolverTypeWrapper & { checkIn?: Maybe, user: ResolversTypes['User'] }>; @@ -3342,7 +3485,6 @@ export type ResolversTypes = { CreateAgendaSectionInput: CreateAgendaSectionInput; CreateCommentError: ResolverTypeWrapper['CreateCommentError']>; CreateCommentPayload: ResolverTypeWrapper & { comment?: Maybe, userErrors: Array }>; - CreateDirectChatError: ResolverTypeWrapper['CreateDirectChatError']>; CreateMemberError: ResolverTypeWrapper['CreateMemberError']>; CreateMemberPayload: ResolverTypeWrapper & { organization?: Maybe, userErrors: Array }>; CreateUserTagInput: CreateUserTagInput; @@ -3353,8 +3495,6 @@ export type ResolversTypes = { DefaultConnectionPageInfo: ResolverTypeWrapper; DeleteAdvertisementPayload: ResolverTypeWrapper & { advertisement?: Maybe }>; DeletePayload: ResolverTypeWrapper; - DirectChat: ResolverTypeWrapper; - DirectChatMessage: ResolverTypeWrapper; Donation: ResolverTypeWrapper; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3370,14 +3510,20 @@ export type ResolversTypes = { EventVolunteer: ResolverTypeWrapper; EventVolunteerGroup: ResolverTypeWrapper; EventVolunteerGroupInput: EventVolunteerGroupInput; + EventVolunteerGroupOrderByInput: EventVolunteerGroupOrderByInput; EventVolunteerGroupWhereInput: EventVolunteerGroupWhereInput; EventVolunteerInput: EventVolunteerInput; EventVolunteerResponse: EventVolunteerResponse; + EventVolunteerWhereInput: EventVolunteerWhereInput; + EventVolunteersOrderByInput: EventVolunteersOrderByInput; EventWhereInput: EventWhereInput; ExtendSession: ResolverTypeWrapper; Feedback: ResolverTypeWrapper; FeedbackInput: FeedbackInput; FieldError: ResolverTypeWrapper['FieldError']>; + File: ResolverTypeWrapper; + FileMetadata: ResolverTypeWrapper; + FileVisibility: FileVisibility; Float: ResolverTypeWrapper; ForgotPasswordData: ForgotPasswordData; Frequency: Frequency; @@ -3391,8 +3537,8 @@ export type ResolversTypes = { FundraisingCampaignPledge: ResolverTypeWrapper; Gender: Gender; Group: ResolverTypeWrapper; - GroupChat: ResolverTypeWrapper; - GroupChatMessage: ResolverTypeWrapper; + Hash: ResolverTypeWrapper; + HoursHistory: ResolverTypeWrapper; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; InvalidCursor: ResolverTypeWrapper; @@ -3411,8 +3557,6 @@ export type ResolversTypes = { MembershipRequest: ResolverTypeWrapper; MembershipRequestsWhereInput: MembershipRequestsWhereInput; Message: ResolverTypeWrapper; - MessageChat: ResolverTypeWrapper; - MessageChatInput: MessageChatInput; MinimumLengthError: ResolverTypeWrapper; MinimumValueError: ResolverTypeWrapper; Mutation: ResolverTypeWrapper<{}>; @@ -3457,6 +3601,7 @@ export type ResolversTypes = { Status: Status; String: ResolverTypeWrapper; Subscription: ResolverTypeWrapper<{}>; + TagActionsInput: TagActionsInput; Time: ResolverTypeWrapper; ToggleUserTagAssignInput: ToggleUserTagAssignInput; Translation: ResolverTypeWrapper; @@ -3491,6 +3636,7 @@ export type ResolversTypes = { UserData: ResolverTypeWrapper & { appUserProfile?: Maybe, user: ResolversTypes['User'] }>; UserFamily: ResolverTypeWrapper; UserInput: UserInput; + UserNameWhereInput: UserNameWhereInput; UserNotAuthorizedAdminError: ResolverTypeWrapper; UserNotAuthorizedError: ResolverTypeWrapper; UserNotFoundError: ResolverTypeWrapper; @@ -3498,6 +3644,12 @@ export type ResolversTypes = { UserPhone: ResolverTypeWrapper; UserPhoneInput: UserPhoneInput; UserTag: ResolverTypeWrapper; + UserTagNameWhereInput: UserTagNameWhereInput; + UserTagSortedByInput: UserTagSortedByInput; + UserTagUsersAssignedToSortedByInput: UserTagUsersAssignedToSortedByInput; + UserTagUsersAssignedToWhereInput: UserTagUsersAssignedToWhereInput; + UserTagUsersToAssignToWhereInput: UserTagUsersToAssignToWhereInput; + UserTagWhereInput: UserTagWhereInput; UserTagsConnection: ResolverTypeWrapper & { edges: Array }>; UserTagsConnectionEdge: ResolverTypeWrapper & { node: ResolversTypes['UserTag'] }>; UserType: UserType; @@ -3508,10 +3660,14 @@ export type ResolversTypes = { VenueInput: VenueInput; VenueOrderByInput: VenueOrderByInput; VenueWhereInput: VenueWhereInput; + VolunteerMembership: ResolverTypeWrapper; + VolunteerMembershipInput: VolunteerMembershipInput; + VolunteerMembershipOrderByInput: VolunteerMembershipOrderByInput; + VolunteerMembershipWhereInput: VolunteerMembershipWhereInput; + VolunteerRank: ResolverTypeWrapper & { user: ResolversTypes['User'] }>; + VolunteerRankWhereInput: VolunteerRankWhereInput; WeekDays: WeekDays; - createChatInput: CreateChatInput; - createDirectChatPayload: ResolverTypeWrapper & { directChat?: Maybe, userErrors: Array }>; - createGroupChatInput: CreateGroupChatInput; + chatInput: ChatInput; createUserFamilyInput: CreateUserFamilyInput; }; @@ -3521,6 +3677,7 @@ export type ResolversParentTypes = { ActionItemCategory: InterfaceActionItemCategoryModel; ActionItemCategoryWhereInput: ActionItemCategoryWhereInput; ActionItemWhereInput: ActionItemWhereInput; + AddPeopleToUserTagInput: AddPeopleToUserTagInput; Address: Address; AddressInput: AddressInput; Advertisement: InterfaceAdvertisementModel; @@ -3536,6 +3693,8 @@ export type ResolversParentTypes = { AuthData: Omit & { appUserProfile: ResolversParentTypes['AppUserProfile'], user: ResolversParentTypes['User'] }; Boolean: Scalars['Boolean']['output']; CampaignWhereInput: CampaignWhereInput; + Chat: InterfaceChatModel; + ChatMessage: InterfaceChatMessageModel; CheckIn: InterfaceCheckInModel; CheckInCheckOutInput: CheckInCheckOutInput; CheckInStatus: Omit & { checkIn?: Maybe, user: ResolversParentTypes['User'] }; @@ -3556,7 +3715,6 @@ export type ResolversParentTypes = { CreateAgendaSectionInput: CreateAgendaSectionInput; CreateCommentError: ResolversUnionTypes['CreateCommentError']; CreateCommentPayload: Omit & { comment?: Maybe, userErrors: Array }; - CreateDirectChatError: ResolversUnionTypes['CreateDirectChatError']; CreateMemberError: ResolversUnionTypes['CreateMemberError']; CreateMemberPayload: Omit & { organization?: Maybe, userErrors: Array }; CreateUserTagInput: CreateUserTagInput; @@ -3566,8 +3724,6 @@ export type ResolversParentTypes = { DefaultConnectionPageInfo: DefaultConnectionPageInfo; DeleteAdvertisementPayload: Omit & { advertisement?: Maybe }; DeletePayload: DeletePayload; - DirectChat: InterfaceDirectChatModel; - DirectChatMessage: InterfaceDirectChatMessageModel; Donation: InterfaceDonationModel; DonationWhereInput: DonationWhereInput; EditVenueInput: EditVenueInput; @@ -3582,11 +3738,14 @@ export type ResolversParentTypes = { EventVolunteerGroupInput: EventVolunteerGroupInput; EventVolunteerGroupWhereInput: EventVolunteerGroupWhereInput; EventVolunteerInput: EventVolunteerInput; + EventVolunteerWhereInput: EventVolunteerWhereInput; EventWhereInput: EventWhereInput; ExtendSession: ExtendSession; Feedback: InterfaceFeedbackModel; FeedbackInput: FeedbackInput; FieldError: ResolversInterfaceTypes['FieldError']; + File: File; + FileMetadata: FileMetadata; Float: Scalars['Float']['output']; ForgotPasswordData: ForgotPasswordData; Fund: InterfaceFundModel; @@ -3597,8 +3756,8 @@ export type ResolversParentTypes = { FundraisingCampaign: InterfaceFundraisingCampaignModel; FundraisingCampaignPledge: InterfaceFundraisingCampaignPledgesModel; Group: InterfaceGroupModel; - GroupChat: InterfaceGroupChatModel; - GroupChatMessage: InterfaceGroupChatMessageModel; + Hash: Hash; + HoursHistory: HoursHistory; ID: Scalars['ID']['output']; Int: Scalars['Int']['output']; InvalidCursor: InvalidCursor; @@ -3615,8 +3774,6 @@ export type ResolversParentTypes = { MembershipRequest: InterfaceMembershipRequestModel; MembershipRequestsWhereInput: MembershipRequestsWhereInput; Message: InterfaceMessageModel; - MessageChat: InterfaceMessageChatModel; - MessageChatInput: MessageChatInput; MinimumLengthError: MinimumLengthError; MinimumValueError: MinimumValueError; Mutation: {}; @@ -3654,6 +3811,7 @@ export type ResolversParentTypes = { SocialMediaUrlsInput: SocialMediaUrlsInput; String: Scalars['String']['output']; Subscription: {}; + TagActionsInput: TagActionsInput; Time: Scalars['Time']['output']; ToggleUserTagAssignInput: ToggleUserTagAssignInput; Translation: Translation; @@ -3687,12 +3845,19 @@ export type ResolversParentTypes = { UserData: Omit & { appUserProfile?: Maybe, user: ResolversParentTypes['User'] }; UserFamily: InterfaceUserFamilyModel; UserInput: UserInput; + UserNameWhereInput: UserNameWhereInput; UserNotAuthorizedAdminError: UserNotAuthorizedAdminError; UserNotAuthorizedError: UserNotAuthorizedError; UserNotFoundError: UserNotFoundError; UserPhone: UserPhone; UserPhoneInput: UserPhoneInput; UserTag: InterfaceOrganizationTagUserModel; + UserTagNameWhereInput: UserTagNameWhereInput; + UserTagSortedByInput: UserTagSortedByInput; + UserTagUsersAssignedToSortedByInput: UserTagUsersAssignedToSortedByInput; + UserTagUsersAssignedToWhereInput: UserTagUsersAssignedToWhereInput; + UserTagUsersToAssignToWhereInput: UserTagUsersToAssignToWhereInput; + UserTagWhereInput: UserTagWhereInput; UserTagsConnection: Omit & { edges: Array }; UserTagsConnectionEdge: Omit & { node: ResolversParentTypes['UserTag'] }; UserWhereInput: UserWhereInput; @@ -3701,9 +3866,12 @@ export type ResolversParentTypes = { Venue: InterfaceVenueModel; VenueInput: VenueInput; VenueWhereInput: VenueWhereInput; - createChatInput: CreateChatInput; - createDirectChatPayload: Omit & { directChat?: Maybe, userErrors: Array }; - createGroupChatInput: CreateGroupChatInput; + VolunteerMembership: InterfaceVolunteerMembershipModel; + VolunteerMembershipInput: VolunteerMembershipInput; + VolunteerMembershipWhereInput: VolunteerMembershipWhereInput; + VolunteerRank: Omit & { user: ResolversParentTypes['User'] }; + VolunteerRankWhereInput: VolunteerRankWhereInput; + chatInput: ChatInput; createUserFamilyInput: CreateUserFamilyInput; }; @@ -3720,8 +3888,11 @@ export type RoleDirectiveResolver = { _id?: Resolver; actionItemCategory?: Resolver, ParentType, ContextType>; - allotedHours?: Resolver, ParentType, ContextType>; - assignee?: Resolver, ParentType, ContextType>; + allottedHours?: Resolver, ParentType, ContextType>; + assignee?: Resolver, ParentType, ContextType>; + assigneeGroup?: Resolver, ParentType, ContextType>; + assigneeType?: Resolver; + assigneeUser?: Resolver, ParentType, ContextType>; assigner?: Resolver, ParentType, ContextType>; assignmentDate?: Resolver; completionDate?: Resolver; @@ -3867,6 +4038,34 @@ export type AuthDataResolvers; }; +export type ChatResolvers = { + _id?: Resolver; + admins?: Resolver>>, ParentType, ContextType>; + createdAt?: Resolver; + creator?: Resolver, ParentType, ContextType>; + image?: Resolver, ParentType, ContextType>; + isGroup?: Resolver; + lastMessageId?: Resolver, ParentType, ContextType>; + messages?: Resolver>>, ParentType, ContextType>; + name?: Resolver, ParentType, ContextType>; + organization?: Resolver, ParentType, ContextType>; + updatedAt?: Resolver; + users?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type ChatMessageResolvers = { + _id?: Resolver; + chatMessageBelongsTo?: Resolver; + createdAt?: Resolver; + deletedBy?: Resolver>>, ParentType, ContextType>; + messageContent?: Resolver; + replyTo?: Resolver, ParentType, ContextType>; + sender?: Resolver; + updatedAt?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type CheckInResolvers = { _id?: Resolver; createdAt?: Resolver; @@ -3911,6 +4110,7 @@ export type CommunityResolvers, ParentType, ContextType>; name?: Resolver; socialMediaUrls?: Resolver, ParentType, ContextType>; + timeout?: Resolver, ParentType, ContextType>; websiteLink?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; }; @@ -3956,10 +4156,6 @@ export type CreateCommentPayloadResolvers; }; -export type CreateDirectChatErrorResolvers = { - __resolveType: TypeResolveFn<'OrganizationNotFoundError' | 'UserNotFoundError', ParentType, ContextType>; -}; - export type CreateMemberErrorResolvers = { __resolveType: TypeResolveFn<'MemberNotFoundError' | 'OrganizationNotFoundError' | 'UserNotAuthorizedAdminError' | 'UserNotAuthorizedError' | 'UserNotFoundError', ParentType, ContextType>; }; @@ -3996,28 +4192,6 @@ export type DeletePayloadResolvers; }; -export type DirectChatResolvers = { - _id?: Resolver; - createdAt?: Resolver; - creator?: Resolver, ParentType, ContextType>; - messages?: Resolver>>, ParentType, ContextType>; - organization?: Resolver, ParentType, ContextType>; - updatedAt?: Resolver; - users?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; -}; - -export type DirectChatMessageResolvers = { - _id?: Resolver; - createdAt?: Resolver; - directChatMessageBelongsTo?: Resolver; - messageContent?: Resolver; - receiver?: Resolver; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type DonationResolvers = { _id?: Resolver; amount?: Resolver; @@ -4070,6 +4244,8 @@ export type EventResolvers, ParentType, ContextType>; title?: Resolver; updatedAt?: Resolver; + volunteerGroups?: Resolver>>, ParentType, ContextType>; + volunteers?: Resolver>>, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4090,13 +4266,15 @@ export type EventAttendeeResolvers = { _id?: Resolver; + assignments?: Resolver>>, ParentType, ContextType>; createdAt?: Resolver; creator?: Resolver, ParentType, ContextType>; event?: Resolver, ParentType, ContextType>; - group?: Resolver, ParentType, ContextType>; - isAssigned?: Resolver, ParentType, ContextType>; - isInvited?: Resolver, ParentType, ContextType>; - response?: Resolver, ParentType, ContextType>; + groups?: Resolver>>, ParentType, ContextType>; + hasAccepted?: Resolver; + hoursHistory?: Resolver>>, ParentType, ContextType>; + hoursVolunteered?: Resolver; + isPublic?: Resolver; updatedAt?: Resolver; user?: Resolver; __isTypeOf?: IsTypeOfResolverFn; @@ -4104,8 +4282,10 @@ export type EventVolunteerResolvers = { _id?: Resolver; + assignments?: Resolver>>, ParentType, ContextType>; createdAt?: Resolver; creator?: Resolver, ParentType, ContextType>; + description?: Resolver, ParentType, ContextType>; event?: Resolver, ParentType, ContextType>; leader?: Resolver; name?: Resolver, ParentType, ContextType>; @@ -4137,6 +4317,32 @@ export type FieldErrorResolvers, ParentType, ContextType>; }; +export type FileResolvers = { + _id?: Resolver; + archived?: Resolver; + archivedAt?: Resolver, ParentType, ContextType>; + backupStatus?: Resolver; + createdAt?: Resolver; + encryption?: Resolver; + fileName?: Resolver; + hash?: Resolver; + metadata?: Resolver; + mimeType?: Resolver; + referenceCount?: Resolver; + size?: Resolver; + status?: Resolver; + updatedAt?: Resolver; + uri?: Resolver; + visibility?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type FileMetadataResolvers = { + bucketName?: Resolver; + objectKey?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type FundResolvers = { _id?: Resolver; campaigns?: Resolver>>, ParentType, ContextType>; @@ -4189,25 +4395,15 @@ export type GroupResolvers; }; -export type GroupChatResolvers = { - _id?: Resolver; - createdAt?: Resolver; - creator?: Resolver, ParentType, ContextType>; - messages?: Resolver>>, ParentType, ContextType>; - organization?: Resolver; - title?: Resolver; - updatedAt?: Resolver; - users?: Resolver, ParentType, ContextType>; +export type HashResolvers = { + algorithm?: Resolver; + value?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; -export type GroupChatMessageResolvers = { - _id?: Resolver; - createdAt?: Resolver; - groupChatMessageBelongsTo?: Resolver; - messageContent?: Resolver; - sender?: Resolver; - updatedAt?: Resolver; +export type HoursHistoryResolvers = { + date?: Resolver; + hours?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4282,17 +4478,6 @@ export type MessageResolvers; }; -export type MessageChatResolvers = { - _id?: Resolver; - createdAt?: Resolver; - languageBarrier?: Resolver, ParentType, ContextType>; - message?: Resolver; - receiver?: Resolver; - sender?: Resolver; - updatedAt?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}; - export type MinimumLengthErrorResolvers = { limit?: Resolver; message?: Resolver; @@ -4313,12 +4498,12 @@ export type MutationResolvers>; addOrganizationCustomField?: Resolver>; addOrganizationImage?: Resolver>; + addPeopleToUserTag?: Resolver, ParentType, ContextType, RequireFields>; addPledgeToFundraisingCampaign?: Resolver>; addUserCustomData?: Resolver>; addUserImage?: Resolver>; - addUserToGroupChat?: Resolver>; addUserToUserFamily?: Resolver>; - adminRemoveGroup?: Resolver>; + assignToUserTags?: Resolver, ParentType, ContextType, RequireFields>; assignUserTag?: Resolver, ParentType, ContextType, RequireFields>; blockPluginCreationBySuperadmin?: Resolver>; blockUser?: Resolver>; @@ -4332,8 +4517,8 @@ export type MutationResolvers>; createAgendaItem?: Resolver>; createAgendaSection?: Resolver>; + createChat?: Resolver, ParentType, ContextType, RequireFields>; createComment?: Resolver, ParentType, ContextType, RequireFields>; - createDirectChat?: Resolver>; createDonation?: Resolver>; createEvent?: Resolver>; createEventVolunteer?: Resolver>; @@ -4341,9 +4526,7 @@ export type MutationResolvers>; createFundraisingCampaign?: Resolver>; createFundraisingCampaignPledge?: Resolver>; - createGroupChat?: Resolver>; createMember?: Resolver>; - createMessageChat?: Resolver>; createNote?: Resolver>; createOrganization?: Resolver>; createPlugin?: Resolver>; @@ -4352,6 +4535,7 @@ export type MutationResolvers>; createUserTag?: Resolver, ParentType, ContextType, RequireFields>; createVenue?: Resolver, ParentType, ContextType, RequireFields>; + createVolunteerMembership?: Resolver>; deleteAdvertisement?: Resolver, ParentType, ContextType, RequireFields>; deleteAgendaCategory?: Resolver>; deleteDonationById?: Resolver>; @@ -4378,13 +4562,12 @@ export type MutationResolvers>; removeAgendaSection?: Resolver>; removeComment?: Resolver, ParentType, ContextType, RequireFields>; - removeDirectChat?: Resolver>; removeEvent?: Resolver>; removeEventAttendee?: Resolver>; removeEventVolunteer?: Resolver>; removeEventVolunteerGroup?: Resolver>; + removeFromUserTags?: Resolver, ParentType, ContextType, RequireFields>; removeFundraisingCampaignPledge?: Resolver>; - removeGroupChat?: Resolver>; removeMember?: Resolver>; removeOrganization?: Resolver>; removeOrganizationCustomField?: Resolver>; @@ -4393,7 +4576,6 @@ export type MutationResolvers; removeUserCustomData?: Resolver>; removeUserFamily?: Resolver>; - removeUserFromGroupChat?: Resolver>; removeUserFromUserFamily?: Resolver>; removeUserImage?: Resolver; removeUserTag?: Resolver, ParentType, ContextType, RequireFields>; @@ -4401,8 +4583,7 @@ export type MutationResolvers; saveFcmToken?: Resolver>; sendMembershipRequest?: Resolver>; - sendMessageToDirectChat?: Resolver>; - sendMessageToGroupChat?: Resolver>; + sendMessageToChat?: Resolver>; signUp?: Resolver>; togglePostPin?: Resolver>; unassignUserTag?: Resolver, ParentType, ContextType, RequireFields>; @@ -4419,7 +4600,7 @@ export type MutationResolvers>; updateEvent?: Resolver>; updateEventVolunteer?: Resolver>; - updateEventVolunteerGroup?: Resolver>; + updateEventVolunteerGroup?: Resolver>; updateFund?: Resolver>; updateFundraisingCampaign?: Resolver>; updateFundraisingCampaignPledge?: Resolver>; @@ -4428,10 +4609,12 @@ export type MutationResolvers>; updatePluginStatus?: Resolver>; updatePost?: Resolver>; + updateSessionTimeout?: Resolver>; updateUserPassword?: Resolver>; updateUserProfile?: Resolver>; updateUserRoleInOrganization?: Resolver>; updateUserTag?: Resolver, ParentType, ContextType, RequireFields>; + updateVolunteerMembership?: Resolver>; }; export type NoteResolvers = { @@ -4549,7 +4732,7 @@ export type PostResolvers>>, ParentType, ContextType>; createdAt?: Resolver; creator?: Resolver, ParentType, ContextType>; - imageUrl?: Resolver, ParentType, ContextType>; + file?: Resolver, ParentType, ContextType>; likeCount?: Resolver, ParentType, ContextType>; likedBy?: Resolver>>, ParentType, ContextType>; organization?: Resolver; @@ -4557,7 +4740,6 @@ export type PostResolvers; title?: Resolver, ParentType, ContextType>; updatedAt?: Resolver; - videoUrl?: Resolver, ParentType, ContextType>; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4583,20 +4765,20 @@ export type QueryResolvers>>, ParentType, ContextType, RequireFields>; actionItemsByEvent?: Resolver>>, ParentType, ContextType, RequireFields>; actionItemsByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; + actionItemsByUser?: Resolver>>, ParentType, ContextType, RequireFields>; adminPlugin?: Resolver>>, ParentType, ContextType, RequireFields>; advertisementsConnection?: Resolver, ParentType, ContextType, Partial>; agendaCategory?: Resolver>; agendaItemByEvent?: Resolver>>, ParentType, ContextType, RequireFields>; agendaItemByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; agendaItemCategoriesByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; + chatById?: Resolver>; + chatsByUserId?: Resolver>>, ParentType, ContextType, RequireFields>; checkAuth?: Resolver; customDataByOrganization?: Resolver, ParentType, ContextType, RequireFields>; customFieldsByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; - directChatById?: Resolver, ParentType, ContextType, RequireFields>; - directChatsByUserID?: Resolver>>, ParentType, ContextType, RequireFields>; - directChatsMessagesByChatID?: Resolver>>, ParentType, ContextType, RequireFields>; event?: Resolver, ParentType, ContextType, RequireFields>; - eventVolunteersByEvent?: Resolver>>, ParentType, ContextType, RequireFields>; + eventsAttendedByUser?: Resolver>>, ParentType, ContextType, Partial>; eventsByOrganization?: Resolver>>, ParentType, ContextType, Partial>; eventsByOrganizationConnection?: Resolver, ParentType, ContextType, Partial>; fundsByOrganization?: Resolver>>, ParentType, ContextType, RequireFields>; @@ -4611,19 +4793,20 @@ export type QueryResolvers, ParentType, ContextType, RequireFields>; getEventAttendeesByEventId?: Resolver>>, ParentType, ContextType, RequireFields>; getEventInvitesByUserId?: Resolver, ParentType, ContextType, RequireFields>; - getEventVolunteerGroups?: Resolver>, ParentType, ContextType, Partial>; + getEventVolunteerGroups?: Resolver>, ParentType, ContextType, RequireFields>; + getEventVolunteers?: Resolver>, ParentType, ContextType, RequireFields>; getFundById?: Resolver>; getFundraisingCampaignPledgeById?: Resolver>; getFundraisingCampaigns?: Resolver>, ParentType, ContextType, Partial>; getNoteById?: Resolver>; getPledgesByUserId?: Resolver>>, ParentType, ContextType, RequireFields>; getPlugins?: Resolver>>, ParentType, ContextType>; + getRecurringEvents?: Resolver>>, ParentType, ContextType, RequireFields>; getUserTag?: Resolver, ParentType, ContextType, RequireFields>; - getUserTagAncestors?: Resolver>>, ParentType, ContextType, RequireFields>; getVenueByOrgId?: Resolver>>, ParentType, ContextType, RequireFields>; + getVolunteerMembership?: Resolver>, ParentType, ContextType, RequireFields>; + getVolunteerRanks?: Resolver>, ParentType, ContextType, RequireFields>; getlanguage?: Resolver>>, ParentType, ContextType, RequireFields>; - groupChatById?: Resolver, ParentType, ContextType, RequireFields>; - groupChatsByUserId?: Resolver>>, ParentType, ContextType, RequireFields>; hasSubmittedFeedback?: Resolver, ParentType, ContextType, RequireFields>; isSampleOrganization?: Resolver>; joinedOrganizations?: Resolver>>, ParentType, ContextType, Partial>; @@ -4671,9 +4854,7 @@ export type SocialMediaUrlsResolvers = { - directMessageChat?: SubscriptionResolver, "directMessageChat", ParentType, ContextType>; - messageSentToDirectChat?: SubscriptionResolver, "messageSentToDirectChat", ParentType, ContextType, RequireFields>; - messageSentToGroupChat?: SubscriptionResolver, "messageSentToGroupChat", ParentType, ContextType, RequireFields>; + messageSentToChat?: SubscriptionResolver, "messageSentToChat", ParentType, ContextType, RequireFields>; onPluginUpdate?: SubscriptionResolver, "onPluginUpdate", ParentType, ContextType>; }; @@ -4722,6 +4903,8 @@ export type UserResolvers; employmentStatus?: Resolver, ParentType, ContextType>; eventAdmin?: Resolver>>, ParentType, ContextType>; + eventsAttended?: Resolver>>, ParentType, ContextType>; + file?: Resolver, ParentType, ContextType>; firstName?: Resolver; gender?: Resolver, ParentType, ContextType>; identifier?: Resolver; @@ -4794,11 +4977,13 @@ export type UserPhoneResolvers = { _id?: Resolver; + ancestorTags?: Resolver>>, ParentType, ContextType>; childTags?: Resolver, ParentType, ContextType, Partial>; name?: Resolver; organization?: Resolver, ParentType, ContextType>; parentTag?: Resolver, ParentType, ContextType>; usersAssignedTo?: Resolver, ParentType, ContextType, Partial>; + usersToAssignTo?: Resolver, ParentType, ContextType, Partial>; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4838,9 +5023,23 @@ export type VenueResolvers; }; -export type CreateDirectChatPayloadResolvers = { - directChat?: Resolver, ParentType, ContextType>; - userErrors?: Resolver, ParentType, ContextType>; +export type VolunteerMembershipResolvers = { + _id?: Resolver; + createdAt?: Resolver; + createdBy?: Resolver, ParentType, ContextType>; + event?: Resolver; + group?: Resolver, ParentType, ContextType>; + status?: Resolver; + updatedAt?: Resolver; + updatedBy?: Resolver, ParentType, ContextType>; + volunteer?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type VolunteerRankResolvers = { + hoursVolunteered?: Resolver; + rank?: Resolver; + user?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4859,6 +5058,8 @@ export type Resolvers = { Any?: GraphQLScalarType; AppUserProfile?: AppUserProfileResolvers; AuthData?: AuthDataResolvers; + Chat?: ChatResolvers; + ChatMessage?: ChatMessageResolvers; CheckIn?: CheckInResolvers; CheckInStatus?: CheckInStatusResolvers; CheckOut?: CheckOutResolvers; @@ -4872,7 +5073,6 @@ export type Resolvers = { CreateAdvertisementPayload?: CreateAdvertisementPayloadResolvers; CreateCommentError?: CreateCommentErrorResolvers; CreateCommentPayload?: CreateCommentPayloadResolvers; - CreateDirectChatError?: CreateDirectChatErrorResolvers; CreateMemberError?: CreateMemberErrorResolvers; CreateMemberPayload?: CreateMemberPayloadResolvers; Date?: GraphQLScalarType; @@ -4880,8 +5080,6 @@ export type Resolvers = { DefaultConnectionPageInfo?: DefaultConnectionPageInfoResolvers; DeleteAdvertisementPayload?: DeleteAdvertisementPayloadResolvers; DeletePayload?: DeletePayloadResolvers; - DirectChat?: DirectChatResolvers; - DirectChatMessage?: DirectChatMessageResolvers; Donation?: DonationResolvers; EmailAddress?: GraphQLScalarType; Error?: ErrorResolvers; @@ -4892,12 +5090,14 @@ export type Resolvers = { ExtendSession?: ExtendSessionResolvers; Feedback?: FeedbackResolvers; FieldError?: FieldErrorResolvers; + File?: FileResolvers; + FileMetadata?: FileMetadataResolvers; Fund?: FundResolvers; FundraisingCampaign?: FundraisingCampaignResolvers; FundraisingCampaignPledge?: FundraisingCampaignPledgeResolvers; Group?: GroupResolvers; - GroupChat?: GroupChatResolvers; - GroupChatMessage?: GroupChatMessageResolvers; + Hash?: HashResolvers; + HoursHistory?: HoursHistoryResolvers; InvalidCursor?: InvalidCursorResolvers; JSON?: GraphQLScalarType; Language?: LanguageResolvers; @@ -4909,7 +5109,6 @@ export type Resolvers = { MemberNotFoundError?: MemberNotFoundErrorResolvers; MembershipRequest?: MembershipRequestResolvers; Message?: MessageResolvers; - MessageChat?: MessageChatResolvers; MinimumLengthError?: MinimumLengthErrorResolvers; MinimumValueError?: MinimumValueErrorResolvers; Mutation?: MutationResolvers; @@ -4955,7 +5154,8 @@ export type Resolvers = { UsersConnection?: UsersConnectionResolvers; UsersConnectionEdge?: UsersConnectionEdgeResolvers; Venue?: VenueResolvers; - createDirectChatPayload?: CreateDirectChatPayloadResolvers; + VolunteerMembership?: VolunteerMembershipResolvers; + VolunteerRank?: VolunteerRankResolvers; }; export type DirectiveResolvers = { diff --git a/src/utilities/adminCheck.ts b/src/utilities/adminCheck.ts index 3d49abcd83..8f1b7ac80d 100644 --- a/src/utilities/adminCheck.ts +++ b/src/utilities/adminCheck.ts @@ -12,12 +12,14 @@ import { AppUserProfile } from "../models"; * This is a utility method. * @param userId - The ID of the current user. It can be a string or a Types.ObjectId. * @param organization - The organization data of `InterfaceOrganization` type. + * @param throwError - A boolean value to determine if the function should throw an error. Default is `true`. * @returns `True` or `False`. */ export const adminCheck = async ( userId: string | Types.ObjectId, organization: InterfaceOrganization, -): Promise => { + throwError: boolean = true, +): Promise => { /** * Check if the user is listed as an admin in the organization. * Compares the user ID with the admin IDs in the organization. @@ -55,10 +57,15 @@ export const adminCheck = async ( * If the user is neither an organization admin nor a super admin, throw an UnauthorizedError. */ if (!userIsOrganizationAdmin && !isUserSuperAdmin) { - throw new errors.UnauthorizedError( - requestContext.translate(`${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`), - USER_NOT_AUTHORIZED_ADMIN.CODE, - USER_NOT_AUTHORIZED_ADMIN.PARAM, - ); + if (throwError) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ADMIN.MESSAGE), + USER_NOT_AUTHORIZED_ADMIN.CODE, + USER_NOT_AUTHORIZED_ADMIN.PARAM, + ); + } else { + return false; + } } + return true; }; diff --git a/src/utilities/auth.ts b/src/utilities/auth.ts index 84389ac1f4..9df4712c76 100644 --- a/src/utilities/auth.ts +++ b/src/utilities/auth.ts @@ -1,7 +1,7 @@ import jwt from "jsonwebtoken"; import { ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRET } from "../constants"; import type { InterfaceAppUserProfile, InterfaceUser } from "../models"; -import { User } from "../models"; +import { Community, User } from "../models"; /** * Interface representing the payload of a JWT token. @@ -22,10 +22,17 @@ export interface InterfaceJwtTokenPayload { * @param appUserProfile - Application user profile data * @returns JSON Web Token string payload */ -export const createAccessToken = ( +export const createAccessToken = async ( user: InterfaceUser, appUserProfile: InterfaceAppUserProfile, -): string => { +): Promise => { + let timeout = 30; //in minutes + const community = await Community.findOne().lean(); + + if (community) { + timeout = community.timeout; + } + return jwt.sign( { tokenVersion: appUserProfile.tokenVersion, @@ -33,6 +40,7 @@ export const createAccessToken = ( firstName: user.firstName, lastName: user.lastName, email: user.email, + timeout: timeout, }, ACCESS_TOKEN_SECRET as string, { diff --git a/src/utilities/checks.ts b/src/utilities/checks.ts new file mode 100644 index 0000000000..bac1389537 --- /dev/null +++ b/src/utilities/checks.ts @@ -0,0 +1,153 @@ +import { + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../constants"; +import { errors, requestContext } from "../libraries"; +import type { + InterfaceAppUserProfile, + InterfaceEventVolunteer, + InterfaceEventVolunteerGroup, + InterfaceUser, + InterfaceVolunteerMembership, +} from "../models"; +import { + AppUserProfile, + EventVolunteer, + EventVolunteerGroup, + User, + VolunteerMembership, +} from "../models"; +import { cacheAppUserProfile } from "../services/AppUserProfileCache/cacheAppUserProfile"; +import { findAppUserProfileCache } from "../services/AppUserProfileCache/findAppUserProfileCache"; +import { cacheUsers } from "../services/UserCache/cacheUser"; +import { findUserInCache } from "../services/UserCache/findUserInCache"; + +/** + * This function checks if the user exists. + * @param userId - user id + * @returns User + */ + +export const checkUserExists = async ( + userId: string, +): Promise => { + let currentUser: InterfaceUser | null; + const userFoundInCache = await findUserInCache([userId]); + currentUser = userFoundInCache[0]; + + if (currentUser === null) { + currentUser = await User.findById(userId).lean(); + if (currentUser !== null) await cacheUsers([currentUser]); + } + + if (!currentUser) { + throw new errors.NotFoundError( + requestContext.translate(USER_NOT_FOUND_ERROR.MESSAGE), + USER_NOT_FOUND_ERROR.CODE, + USER_NOT_FOUND_ERROR.PARAM, + ); + } + return currentUser; +}; + +/** + * This function checks if the user has an app profile. + * @param user - user object + * @returns AppUserProfile + */ +export const checkAppUserProfileExists = async ( + user: InterfaceUser, +): Promise => { + let currentUserAppProfile: InterfaceAppUserProfile | null; + const appUserProfileFoundInCache = await findAppUserProfileCache([ + user.appUserProfileId?.toString(), + ]); + currentUserAppProfile = appUserProfileFoundInCache[0]; + if (currentUserAppProfile === null) { + currentUserAppProfile = await AppUserProfile.findOne({ + userId: user._id, + }).lean(); + if (currentUserAppProfile !== null) { + await cacheAppUserProfile([currentUserAppProfile]); + } + } + if (!currentUserAppProfile) { + throw new errors.UnauthorizedError( + requestContext.translate(USER_NOT_AUTHORIZED_ERROR.MESSAGE), + USER_NOT_AUTHORIZED_ERROR.CODE, + USER_NOT_AUTHORIZED_ERROR.PARAM, + ); + } + return currentUserAppProfile; +}; + +/** + * This function checks if the event volunteer exists. + * @param volunteerId - event volunteer id + * @returns EventVolunteer + */ +export const checkEventVolunteerExists = async ( + volunteerId: string, +): Promise => { + const volunteer = await EventVolunteer.findById(volunteerId); + + if (!volunteer) { + throw new errors.NotFoundError( + requestContext.translate(EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE), + EVENT_VOLUNTEER_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_NOT_FOUND_ERROR.PARAM, + ); + } + + return volunteer; +}; + +/** + * This function checks if the volunteer group exists. + * @param groupId - event volunteer group id + * @returns EventVolunteerGroup + */ + +export const checkVolunteerGroupExists = async ( + groupId: string, +): Promise => { + const volunteerGroup = await EventVolunteerGroup.findOne({ + _id: groupId, + }); + + if (!volunteerGroup) { + throw new errors.NotFoundError( + requestContext.translate(EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE), + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.PARAM, + ); + } + return volunteerGroup; +}; + +/** + * This function checks if the volunteerMembership exists. + * @param membershipId - id + * @returns VolunteerMembership + */ +export const checkVolunteerMembershipExists = async ( + membershipId: string, +): Promise => { + const volunteerMembership = await VolunteerMembership.findOne({ + _id: membershipId, + }); + + if (!volunteerMembership) { + throw new errors.NotFoundError( + requestContext.translate( + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR.MESSAGE, + ), + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR.CODE, + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR.PARAM, + ); + } + return volunteerMembership; +}; diff --git a/src/utilities/encodedImageStorage/deletePreviousFile.ts b/src/utilities/encodedImageStorage/deletePreviousFile.ts new file mode 100644 index 0000000000..defeff0e57 --- /dev/null +++ b/src/utilities/encodedImageStorage/deletePreviousFile.ts @@ -0,0 +1,38 @@ +import { File } from "../../models"; +import { deleteFile } from "../../REST/services/minio"; +import { BUCKET_NAME } from "../../config/minio"; + +/** + * Deletes a file from the storage and database if its reference count is 1. + * Otherwise, decrements the reference count in the database by 1. + * + * @param fileId - The ID of the file to be deleted or updated. + * @param objectKey - The object key in the storage bucket associated with the file. + * @returns A promise that resolves when the file is either deleted or its reference count is updated. + */ +export const deletePreviousFile = async ( + fileId: string, + objectKey: string, +): Promise => { + const file = await File.findOne({ + _id: fileId, + }); + + if (file?.referenceCount === 1) { + await deleteFile(BUCKET_NAME as string, objectKey); + await File.deleteOne({ + _id: fileId, + }); + } else { + await File.findOneAndUpdate( + { + _id: fileId, + }, + { + $inc: { + referenceCount: -1, + }, + }, + ); + } +}; diff --git a/src/utilities/isValidMimeType.ts b/src/utilities/isValidMimeType.ts new file mode 100644 index 0000000000..1a121b93f8 --- /dev/null +++ b/src/utilities/isValidMimeType.ts @@ -0,0 +1,17 @@ +import type { FileMimeType } from "../REST/types"; + +/** + * Checks if the provided mimetype is valid. + * @param mimetype - The mimetype to check. + * @returns True if the mimetype is valid, false otherwise. + */ +export const isValidMimeType = (mimetype: string): mimetype is FileMimeType => { + const allowedMimeTypes: FileMimeType[] = [ + "image/jpeg", + "image/png", + "image/gif", + "image/webp", + "video/mp4", + ]; + return allowedMimeTypes.includes(mimetype as FileMimeType); +}; diff --git a/src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionFilter.ts b/src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionFilter.ts new file mode 100644 index 0000000000..e7f6d88a2a --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionFilter.ts @@ -0,0 +1,67 @@ +import type { GraphQLConnectionTraversalDirection } from "../graphQLConnection"; +import type { + ParseSortedByResult, + ParseUserTagWhereResult, +} from "../userTagsPaginationUtils"; + +/** + * This is typescript type of the object returned from function `getUserTagGraphQLConnectionFilter`. + */ +type BaseUserTagGraphQLConnectionFilter = { + name: { + $regex: RegExp; + }; +}; + +type UserTagGraphQLConnectionFilter = BaseUserTagGraphQLConnectionFilter & + ( + | { + _id?: { + $lt: string; + }; + } + | { + _id?: { + $gt: string; + }; + } + ); +/** + * This function is used to get an object containing filtering logic. + */ +export function getUserTagGraphQLConnectionFilter({ + cursor, + direction, + sortById, + nameStartsWith, +}: ParseSortedByResult & + ParseUserTagWhereResult & { + cursor: string | null; + direction: GraphQLConnectionTraversalDirection; + }): UserTagGraphQLConnectionFilter { + const filter = {} as UserTagGraphQLConnectionFilter; + + filter.name = { + $regex: new RegExp( + `^${nameStartsWith.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, + "i", + ), + }; + + if (cursor !== null) { + filter._id = getCursorFilter(cursor, sortById, direction); + } + + return filter; +} + +function getCursorFilter( + cursor: string, + sortById: "ASCENDING" | "DESCENDING", + direction: GraphQLConnectionTraversalDirection, +): { $lt: string } | { $gt: string } { + if (sortById === "ASCENDING") { + return direction === "BACKWARD" ? { $lt: cursor } : { $gt: cursor }; + } + return direction === "BACKWARD" ? { $gt: cursor } : { $lt: cursor }; +} diff --git a/src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionSort.ts b/src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionSort.ts new file mode 100644 index 0000000000..a5082f3d88 --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/getUserTagGraphQLConnectionSort.ts @@ -0,0 +1,45 @@ +import type { GraphQLConnectionTraversalDirection } from "../graphQLConnection"; +import type { ParseSortedByResult } from "../userTagsPaginationUtils"; + +/** + *This is typescript type of the object returned from `getUserTagGraphQLConnectionSort` function. + */ +type UserTagGraphQLConnectionSort = + | { + _id: 1; + } + | { + _id: -1; + }; + +/** + * This function is used to get an object containing sorting logic.a + */ +export function getUserTagGraphQLConnectionSort({ + direction, + sortById, +}: ParseSortedByResult & { + direction: GraphQLConnectionTraversalDirection; +}): UserTagGraphQLConnectionSort { + if (sortById === "ASCENDING") { + if (direction === "BACKWARD") { + return { + _id: -1, + }; + } else { + return { + _id: 1, + }; + } + } else { + if (direction === "BACKWARD") { + return { + _id: 1, + }; + } else { + return { + _id: -1, + }; + } + } +} diff --git a/src/utilities/userTagsPaginationUtils/getUserTagMemberGraphQLConnectionFilter.ts b/src/utilities/userTagsPaginationUtils/getUserTagMemberGraphQLConnectionFilter.ts new file mode 100644 index 0000000000..3d00232d4e --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/getUserTagMemberGraphQLConnectionFilter.ts @@ -0,0 +1,81 @@ +import { Types } from "mongoose"; +import type { GraphQLConnectionTraversalDirection } from "../graphQLConnection"; +import type { + ParseSortedByResult, + ParseUserTagMemberWhereResult, +} from "../userTagsPaginationUtils"; + +/** + * This is typescript type of the object returned from function `getUserTagMemberGraphQLConnectionFilter`. + */ +type BaseUserTagMemberGraphQLConnectionFilter = { + firstName: { + $regex: RegExp; + }; + lastName: { + $regex: RegExp; + }; +}; + +type UserTagMemberGraphQLConnectionFilter = + BaseUserTagMemberGraphQLConnectionFilter & + ( + | { + _id?: { + $lt: Types.ObjectId; + }; + } + | { + _id?: { + $gt: Types.ObjectId; + }; + } + ); + +/** + * This function is used to get an object containing filtering logic. + */ +export function getUserTagMemberGraphQLConnectionFilter({ + cursor, + direction, + sortById, + firstNameStartsWith, + lastNameStartsWith, +}: ParseSortedByResult & + ParseUserTagMemberWhereResult & { + cursor: string | null; + direction: GraphQLConnectionTraversalDirection; + }): UserTagMemberGraphQLConnectionFilter { + const filter = {} as UserTagMemberGraphQLConnectionFilter; + + filter.firstName = { + $regex: new RegExp( + `^${firstNameStartsWith.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, + "i", + ), + }; + filter.lastName = { + $regex: new RegExp( + `^${lastNameStartsWith.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, + "i", + ), + }; + + if (cursor !== null) { + filter._id = getCursorFilter(cursor, sortById, direction); + } + + return filter; +} + +function getCursorFilter( + cursor: string, + sortById: "ASCENDING" | "DESCENDING", + direction: GraphQLConnectionTraversalDirection, +): { $lt: Types.ObjectId } | { $gt: Types.ObjectId } { + const cursorId = new Types.ObjectId(cursor); + if (sortById === "ASCENDING") { + return direction === "BACKWARD" ? { $lt: cursorId } : { $gt: cursorId }; + } + return direction === "BACKWARD" ? { $gt: cursorId } : { $lt: cursorId }; +} diff --git a/src/utilities/userTagsPaginationUtils/index.ts b/src/utilities/userTagsPaginationUtils/index.ts new file mode 100644 index 0000000000..40b6dde26a --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/index.ts @@ -0,0 +1,6 @@ +export * from "./parseUserTagSortedBy"; +export * from "./parseUserTagWhere"; +export * from "./parseUserTagMemberWhere"; +export * from "./getUserTagGraphQLConnectionSort"; +export * from "./getUserTagGraphQLConnectionFilter"; +export * from "./getUserTagMemberGraphQLConnectionFilter"; diff --git a/src/utilities/userTagsPaginationUtils/parseUserTagMemberWhere.ts b/src/utilities/userTagsPaginationUtils/parseUserTagMemberWhere.ts new file mode 100644 index 0000000000..636cb03087 --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/parseUserTagMemberWhere.ts @@ -0,0 +1,73 @@ +import type { UserTagUsersAssignedToWhereInput } from "../../types/generatedGraphQLTypes"; +import type { + DefaultGraphQLArgumentError, + ParseGraphQLConnectionWhereResult, +} from "../graphQLConnection"; + +/** + * Type of the where object returned if the parsing is successful + */ +export type ParseUserTagMemberWhereResult = { + firstNameStartsWith: string; + lastNameStartsWith: string; +}; + +/** + * Function to parse the args.where for UserTag member assignment queries + */ +export function parseUserTagMemberWhere( + where: UserTagUsersAssignedToWhereInput | null | undefined, +): ParseGraphQLConnectionWhereResult { + const errors: DefaultGraphQLArgumentError[] = []; + + if (!where) { + return { + isSuccessful: true, + parsedWhere: { + firstNameStartsWith: "", + lastNameStartsWith: "", + }, + }; + } + + if (!where.firstName && !where.lastName) { + errors.push({ + message: `At least one of firstName or lastName should be provided`, + path: ["where"], + }); + + return { + isSuccessful: false, + errors, + }; + } + + if (where.firstName && typeof where.firstName.starts_with !== "string") { + errors.push({ + message: "Invalid firstName provided. It must be a string.", + path: ["where", "firstName", "starts_with"], + }); + } + + if (where.lastName && typeof where.lastName.starts_with !== "string") { + errors.push({ + message: "Invalid lastName provided. It must be a string.", + path: ["where", "lastName", "starts_with"], + }); + } + + if (errors.length > 0) { + return { + isSuccessful: false, + errors, + }; + } + + return { + isSuccessful: true, + parsedWhere: { + firstNameStartsWith: where.firstName?.starts_with.trim() ?? "", + lastNameStartsWith: where.lastName?.starts_with.trim() ?? "", + }, + }; +} diff --git a/src/utilities/userTagsPaginationUtils/parseUserTagSortedBy.ts b/src/utilities/userTagsPaginationUtils/parseUserTagSortedBy.ts new file mode 100644 index 0000000000..825fca40b6 --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/parseUserTagSortedBy.ts @@ -0,0 +1,50 @@ +import type { + SortedByOrder, + UserTagSortedByInput, +} from "../../types/generatedGraphQLTypes"; +import type { + DefaultGraphQLArgumentError, + ParseGraphQLConnectionSortedByResult, +} from "../graphQLConnection"; + +/** + * type of the sort object returned if the parsing is successful + */ +export type ParseSortedByResult = { + sortById: SortedByOrder; +}; + +/** + * function to parse the args.sortedBy for UserTag queries + */ +export function parseUserTagSortedBy( + sortedBy: UserTagSortedByInput | null | undefined, +): ParseGraphQLConnectionSortedByResult { + const errors: DefaultGraphQLArgumentError[] = []; + + if (!sortedBy) { + return { + isSuccessful: true, + parsedSortedBy: { sortById: "DESCENDING" }, + }; + } + + if (sortedBy.id !== "DESCENDING" && sortedBy.id !== "ASCENDING") { + errors.push({ + message: + "Invalid sortedById provided. It must be a of type SortedByOrder.", + path: ["sortedBy", "id"], + }); + return { + isSuccessful: false, + errors, + }; + } + + return { + isSuccessful: true, + parsedSortedBy: { + sortById: sortedBy.id, + }, + }; +} diff --git a/src/utilities/userTagsPaginationUtils/parseUserTagWhere.ts b/src/utilities/userTagsPaginationUtils/parseUserTagWhere.ts new file mode 100644 index 0000000000..2f0728363d --- /dev/null +++ b/src/utilities/userTagsPaginationUtils/parseUserTagWhere.ts @@ -0,0 +1,61 @@ +import type { UserTagWhereInput } from "../../types/generatedGraphQLTypes"; +import type { + DefaultGraphQLArgumentError, + ParseGraphQLConnectionWhereResult, +} from "../graphQLConnection"; + +/** + * type of the where object returned if the parsing is successful + */ +export type ParseUserTagWhereResult = { + nameStartsWith: string; +}; + +/** + * function to parse the args.where for UserTag queries + */ +export function parseUserTagWhere( + where: UserTagWhereInput | null | undefined, +): ParseGraphQLConnectionWhereResult { + const errors: DefaultGraphQLArgumentError[] = []; + + if (!where) { + return { + isSuccessful: true, + parsedWhere: { + nameStartsWith: "", + }, + }; + } + + if (!where.name) { + errors.push({ + message: "Invalid where input, name should be provided.", + path: ["where"], + }); + + return { + isSuccessful: false, + errors, + }; + } + + if (typeof where.name.starts_with !== "string") { + errors.push({ + message: "Invalid name provided. It must be a string.", + path: ["where", "name"], + }); + + return { + isSuccessful: false, + errors, + }; + } + + return { + isSuccessful: true, + parsedWhere: { + nameStartsWith: where.name.starts_with.trim(), + }, + }; +} diff --git a/tests/helpers/actionItem.ts b/tests/helpers/actionItem.ts index 86eab57629..b1897f717e 100644 --- a/tests/helpers/actionItem.ts +++ b/tests/helpers/actionItem.ts @@ -35,6 +35,7 @@ export const createTestActionItem = async (): Promise< const testActionItem = await ActionItem.create({ creator: testUser?._id, assignee: randomUser?._id, + assigneeType: "EventVolunteer", assigner: testUser?._id, actionItemCategory: testCategory?._id, organization: testOrganization?._id, @@ -59,6 +60,7 @@ export const createNewTestActionItem = async ({ const newTestActionItem = await ActionItem.create({ creator: currUserId, assignee: assignedUserId, + assigneeType: "EventVolunteer", assigner: currUserId, actionItemCategory: actionItemCategoryId, organization: organizationId, @@ -82,6 +84,7 @@ export const createTestActionItems = async (): Promise< const testActionItem1 = await ActionItem.create({ creator: testUser?._id, assignee: randomUser?._id, + assigneeType: "EventVolunteer", assigner: testUser?._id, actionItemCategory: testCategory?._id, organization: testOrganization?._id, @@ -91,6 +94,7 @@ export const createTestActionItems = async (): Promise< const testActionItem2 = await ActionItem.create({ creator: testUser?._id, assignee: randomUser?._id, + assigneeType: "EventVolunteer", assigner: testUser?._id, actionItemCategory: testCategory?._id, organization: testOrganization?._id, @@ -100,6 +104,7 @@ export const createTestActionItems = async (): Promise< await ActionItem.create({ creator: testUser?._id, assignee: randomUser?._id, + assigneeType: "EventVolunteer", assigner: testUser?._id, actionItemCategory: testCategory2?._id, organization: testOrganization?._id, diff --git a/tests/helpers/chat.ts b/tests/helpers/chat.ts new file mode 100644 index 0000000000..b3fa7b468a --- /dev/null +++ b/tests/helpers/chat.ts @@ -0,0 +1,139 @@ +import { nanoid } from "nanoid"; +import type { InterfaceChat, InterfaceChatMessage } from "../../src/models"; +import { Chat, ChatMessage } from "../../src/models"; +import type { TestOrganizationType, TestUserType } from "./userAndOrg"; +import { createTestUserAndOrganization } from "./userAndOrg"; +import type { Document } from "mongoose"; + +export type TestChatType = + | (InterfaceChat & Document) + | null; + +export type TestChatMessageType = + | (InterfaceChatMessage & Document) + | null; + +export const createTestChat = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType] +> => { + const [testUser, testOrganization] = await createTestUserAndOrganization(); + if (testUser && testOrganization) { + const testChat = await Chat.create({ + creatorId: testUser._id, + users: [testUser._id], + organization: testOrganization._id, + isGroup: true, + createdAt: new Date(), + updatedAt: new Date(), + admins: [testUser._id], + }); + + return [testUser, testOrganization, testChat]; + } else { + return [testUser, testOrganization, null]; + } +}; + +export const createTestChatMessage = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] +> => { + const [testUser, testOrganization, testChat] = await createTestChat(); + + if (testChat?.id) { + const chatMessage = await createChatMessage( + testUser?._id, + testChat?._id.toString(), + ); + + if (testChat && testUser) { + const testChatMessage = await ChatMessage.create({ + chatMessageBelongsTo: testChat._id, + sender: testUser._id, + replyTo: chatMessage?._id, + messageContent: `msgContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + type: "STRING", + }); + return [testUser, testOrganization, testChat, testChatMessage]; + } else { + return [testUser, testOrganization, testChat, null]; + } + } + return [testUser, testOrganization, testChat, null]; +}; + +export const createTestChatMessageWithoutReply = async (): Promise< + [TestUserType, TestOrganizationType, TestChatType, TestChatMessageType] +> => { + const [testUser, testOrganization, testChat] = await createTestChat(); + + if (testChat && testUser) { + const testChatMessage = await ChatMessage.create({ + chatMessageBelongsTo: testChat._id, + sender: testUser._id, + replyTo: undefined, + messageContent: `msgContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + type: "STRING", + }); + return [testUser, testOrganization, testChat, testChatMessage]; + } else { + return [testUser, testOrganization, testChat, null]; + } +}; + +export const createTestMessageForMultipleUser = async ( + senderId: string, + organizationId: string, +): Promise => { + const testChat = await Chat.create({ + creatorId: senderId, + users: [senderId], + organization: organizationId, + }); + + await ChatMessage.create({ + chatMessageBelongsTo: testChat._id, + sender: senderId, + messageContent: `messageContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + type: "STRING", + }); + + return testChat; +}; + +export const createTestChatwithUsers = async ( + creator: string, + organizationId: string, + users: string[], +): Promise => { + const testChat = await Chat.create({ + creatorId: creator, + users: users, + organization: organizationId, + isGroup: true, + createdAt: new Date(), + updatedAt: new Date(), + }); + return testChat; +}; + +export const createChatMessage = async ( + senderId: string, + chatId: string, +): Promise => { + const chatMessage = await ChatMessage.create({ + chatMessageBelongsTo: chatId, + sender: senderId, + type: "STRING", + messageContent: `messageContent${nanoid().toLowerCase()}`, + createdAt: new Date(), + updatedAt: new Date(), + }); + + return chatMessage; +}; diff --git a/tests/helpers/directChat.ts b/tests/helpers/directChat.ts deleted file mode 100644 index 96d8888e78..0000000000 --- a/tests/helpers/directChat.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { nanoid } from "nanoid"; -import type { - InterfaceDirectChat, - InterfaceDirectChatMessage, -} from "../../src/models"; -import { DirectChat, DirectChatMessage } from "../../src/models"; -import type { TestOrganizationType, TestUserType } from "./userAndOrg"; -import { createTestUserAndOrganization } from "./userAndOrg"; -import type { Document } from "mongoose"; - -export type TestDirectChatType = - | (InterfaceDirectChat & Document) - | null; - -export type TestDirectChatMessageType = - | (InterfaceDirectChatMessage & - Document) - | null; - -export const createTestDirectChat = async (): Promise< - [TestUserType, TestOrganizationType, TestDirectChatType] -> => { - const [testUser, testOrganization] = await createTestUserAndOrganization(); - if (testUser && testOrganization) { - const testDirectChat = await DirectChat.create({ - creatorId: testUser._id, - users: [testUser._id], - organization: testOrganization._id, - }); - - return [testUser, testOrganization, testDirectChat]; - } else { - return [testUser, testOrganization, null]; - } -}; - -export const createTestDirectChatMessage = async (): Promise< - [ - TestUserType, - TestOrganizationType, - TestDirectChatType, - TestDirectChatMessageType, - ] -> => { - const [testUser, testOrganization, testDirectChat] = - await createTestDirectChat(); - - if (testDirectChat && testUser) { - const testDirectChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: testDirectChat._id, - sender: testUser._id, - receiver: testUser._id, - messageContent: `msgContent${nanoid().toLowerCase()}`, - }); - return [testUser, testOrganization, testDirectChat, testDirectChatMessage]; - } else { - return [testUser, testOrganization, testDirectChat, null]; - } -}; - -export const createTestDirectMessageForMultipleUser = async ( - senderId: string, - receiverId: string, - organizationId: string, -): Promise => { - const testDirectChat = await DirectChat.create({ - creatorId: senderId, - users: [senderId], - organization: organizationId, - }); - - await DirectChatMessage.create({ - directChatMessageBelongsTo: testDirectChat._id, - sender: senderId, - receiver: receiverId, - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return testDirectChat; -}; - -export const createTestDirectChatwithUsers = async ( - creator: string, - organizationId: string, - users: string[], -): Promise => { - const testDirectChat = await DirectChat.create({ - creatorId: creator, - users: users, - organization: organizationId, - }); - return testDirectChat; -}; - -export const createDirectChatMessage = async ( - senderId: string, - receiverId: string, - directChatId: string, -): Promise => { - const directChatMessage = await DirectChatMessage.create({ - directChatMessageBelongsTo: directChatId, - sender: senderId, - receiver: receiverId, - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return directChatMessage; -}; diff --git a/tests/helpers/events.ts b/tests/helpers/events.ts index 75298ee74a..13130906a8 100644 --- a/tests/helpers/events.ts +++ b/tests/helpers/events.ts @@ -1,6 +1,5 @@ import type { Document } from "mongoose"; import { nanoid } from "nanoid"; -import { EventVolunteerResponse } from "../../src/constants"; import type { InterfaceEvent, InterfaceEventVolunteer, @@ -132,12 +131,11 @@ export const createTestEventAndVolunteer = async (): Promise< const [creatorUser, , testEvent] = await createTestEvent(); const volunteerUser = await createTestUser(); const testEventVolunteer = await EventVolunteer.create({ - userId: volunteerUser?._id, - eventId: testEvent?._id, - isInvited: true, - isAssigned: false, - creatorId: creatorUser?._id, - response: EventVolunteerResponse.NO, + user: volunteerUser?._id, + event: testEvent?._id, + creator: creatorUser?._id, + hasAccepted: false, + isPublic: false, }); return [volunteerUser, creatorUser, testEvent, testEventVolunteer]; @@ -157,9 +155,9 @@ export const createTestEventVolunteerGroup = async (): Promise< const testEventVolunteerGroup = await EventVolunteerGroup.create({ name: "testEventVolunteerGroup", volunteersRequired: 1, - eventId: testEvent?._id, - creatorId: creatorUser?._id, - leaderId: creatorUser?._id, + event: testEvent?._id, + creator: creatorUser?._id, + leader: creatorUser?._id, volunteers: [testEventVolunteer?._id], }); diff --git a/tests/helpers/groupChat.ts b/tests/helpers/groupChat.ts deleted file mode 100644 index a7a53b96b9..0000000000 --- a/tests/helpers/groupChat.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { nanoid } from "nanoid"; -import type { - InterfaceGroupChat, - InterfaceGroupChatMessage, -} from "../../src/models"; -import { GroupChat, GroupChatMessage } from "../../src/models"; -import type { TestOrganizationType, TestUserType } from "./userAndOrg"; -import { createTestUserAndOrganization } from "./userAndOrg"; -import type { Document } from "mongoose"; - -export type TestGroupChatType = - | (InterfaceGroupChat & Document) - | null; - -export type TestGroupChatMessageType = - | (InterfaceGroupChatMessage & - Document) - | null; - -export const createTestGroupChat = async (): Promise< - [TestUserType, TestOrganizationType, TestGroupChatType] -> => { - const [testUser, testOrganization] = await createTestUserAndOrganization(); - if (testUser && testOrganization) { - const testGroupChat = await GroupChat.create({ - creatorId: testUser._id, - users: [testUser._id], - organization: testOrganization._id, - title: `title${nanoid().toLowerCase()}`, - }); - - return [testUser, testOrganization, testGroupChat]; - } else { - return [testUser, testOrganization, null]; - } -}; - -export const createTestGroupChatMessage = async (): Promise< - [ - TestUserType, - TestOrganizationType, - TestGroupChatType, - TestGroupChatMessageType, - ] -> => { - const [testUser, testOrganization, testGroupChat] = - await createTestGroupChat(); - - if (testGroupChat && testUser) { - const testGroupChatMessage = await GroupChatMessage.create({ - groupChatMessageBelongsTo: testGroupChat._id, - sender: testUser._id, - createdAt: new Date(), - messageContent: `messageContent${nanoid().toLowerCase()}`, - }); - - return [testUser, testOrganization, testGroupChat, testGroupChatMessage]; - } else { - return [testUser, testOrganization, testGroupChat, null]; - } -}; diff --git a/tests/helpers/minio.ts b/tests/helpers/minio.ts new file mode 100644 index 0000000000..e19f51b809 --- /dev/null +++ b/tests/helpers/minio.ts @@ -0,0 +1,49 @@ +import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3"; +import { ConnectionTimeoutError } from "redis"; + +/** + * Creates an S3 client configured for testing with MinIO + */ +const createTestS3Client = (): S3Client => { + return new S3Client({ + endpoint: process.env.MINIO_ENDPOINT || "http://localhost:9000", + credentials: { + accessKeyId: process.env.MINIO_ROOT_USER || "minioadmin", + secretAccessKey: process.env.MINIO_ROOT_PASSWORD || "minioadmin", + }, + region: "us-east-1", + forcePathStyle: true, + requestHandler: { + connectionTimeout: 3000, + socketTimeout: 3000, + }, + }); +}; + +/** + * Checks if the MinIO server is running and accessible + */ +export const isMinioRunning = async (): Promise => { + const s3Client = createTestS3Client(); + try { + await s3Client.send(new ListBucketsCommand({})); + return true; + } catch (error: unknown) { + if ( + (error instanceof ConnectionTimeoutError && + error.name === "ConnectTimeoutError") || + (error instanceof Error && error.name === "NetworkError") || + (error instanceof Error && + (error as { code?: string }).code === "ECONNREFUSED") + ) { + console.warn( + "\x1b[33m%s\x1b[0m", + "⚠️ MinIO server is not running. Some tests will be skipped.\n" + + "To run all tests, start the MinIO server first.", + ); + return false; + } + // If it's a different kind of error (e.g., authentication), we still consider the server as running + return true; + } +}; diff --git a/tests/helpers/posts.ts b/tests/helpers/posts.ts index c17a7c2752..38e97ca095 100644 --- a/tests/helpers/posts.ts +++ b/tests/helpers/posts.ts @@ -1,7 +1,7 @@ import type { Document } from "mongoose"; import { nanoid } from "nanoid"; import type { InterfaceComment, InterfacePost } from "../../src/models"; -import { Comment, Organization, Post } from "../../src/models"; +import { Comment, Organization, Post, File } from "../../src/models"; import type { TestOrganizationType, TestUserType } from "./userAndOrg"; import { createTestUserAndOrganization } from "./userAndOrg"; @@ -119,19 +119,33 @@ export const createSinglePostwithComment = async ( return [testPost, testComment]; }; -export const createTestSinglePost = async ( +export const createTestPostWithMedia = async ( userId: string, organizationId: string, pinned = false, ): Promise => { + const testFile = await File.create({ + fileName: `test-file-${nanoid()}.jpg`, + mimeType: "image/jpeg", + size: 1024, + hash: { + value: "66465102d50336a0610af4ae66d531cc", + algorithm: "sha256", + }, + uri: "https://example.com/test-file.jpg", + metadata: { + description: "Test file for post", + objectKey: "test-file-object-key", + }, + }); + const testPost = await Post.create({ text: `text${nanoid().toLowerCase()}`, title: `title${nanoid()}`, - imageUrl: `imageUrl${nanoid()}`, - videoUrl: `videoUrl${nanoid()}`, creatorId: userId, organization: organizationId, pinned, + file: testFile, }); return testPost; }; diff --git a/tests/helpers/tags.ts b/tests/helpers/tags.ts index ddbf70cc8a..06d3f49e57 100644 --- a/tests/helpers/tags.ts +++ b/tests/helpers/tags.ts @@ -79,6 +79,7 @@ export const createAndAssignUsersToTag = async ( await TagUser.create({ userId: user?._id, tagId: tag?._id, + organizationId: tag?.organizationId, }); testUsers.push(user); } @@ -93,6 +94,7 @@ export const createTagsAndAssignToUser = async ( await TagUser.create({ userId: testUser?._id, tagId: testTag?._id, + organizationId: testTag?.organizationId, }); const tags: TestUserTagType[] = [testTag]; @@ -108,6 +110,7 @@ export const createTagsAndAssignToUser = async ( await TagUser.create({ tagId: newTag?._id, userId: testUser?._id, + organizationId: newTag.organizationId, }); } diff --git a/tests/helpers/userAndOrg.ts b/tests/helpers/userAndOrg.ts index d7dde673dd..015b86a657 100644 --- a/tests/helpers/userAndOrg.ts +++ b/tests/helpers/userAndOrg.ts @@ -9,8 +9,8 @@ import type { import { AppUserProfile, Organization, User } from "../../src/models"; export type TestOrganizationType = - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (InterfaceOrganization & Document) | null; + | (InterfaceOrganization & Document) + | null; export type TestUserType = | (InterfaceUser & Document) diff --git a/tests/helpers/volunteers.ts b/tests/helpers/volunteers.ts new file mode 100644 index 0000000000..026dc4313a --- /dev/null +++ b/tests/helpers/volunteers.ts @@ -0,0 +1,299 @@ +import type { + InterfaceEventVolunteer, + InterfaceEventVolunteerGroup, + InterfaceVolunteerMembership, +} from "../../src/models"; +import { + ActionItem, + ActionItemCategory, + Event, + EventVolunteer, + EventVolunteerGroup, +} from "../../src/models"; +import type { Document } from "mongoose"; +import { + createTestUser, + createTestUserAndOrganization, + type TestOrganizationType, + type TestUserType, +} from "./userAndOrg"; +import { nanoid } from "nanoid"; +import type { TestEventType } from "./events"; +import type { TestActionItemType } from "./actionItem"; + +export type TestVolunteerType = InterfaceEventVolunteer & Document; +export type TestVolunteerGroupType = InterfaceEventVolunteerGroup & Document; +export type TestVolunteerMembership = InterfaceVolunteerMembership & Document; + +export const createTestVolunteerAndGroup = async (): Promise< + [ + TestUserType, + TestOrganizationType, + TestEventType, + TestVolunteerType, + TestVolunteerGroupType, + ] +> => { + const [testUser, testOrganization] = await createTestUserAndOrganization(); + const randomUser = await createTestUser(); + + const testEvent = await Event.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + allDay: true, + startDate: new Date(), + recurring: false, + isPublic: true, + isRegisterable: true, + creatorId: testUser?._id, + admins: [testUser?._id], + organization: testOrganization?._id, + volunteers: [], + volunteerGroups: [], + }); + + const testVolunteer = await EventVolunteer.create({ + creator: randomUser?._id, + event: testEvent?._id, + user: testUser?._id, + groups: [], + assignments: [], + }); + + // create a volunteer group with testVolunteer as a member & leader + const testVolunteerGroup = await EventVolunteerGroup.create({ + creator: randomUser?._id, + event: testEvent?._id, + volunteers: [testVolunteer?._id], + leader: testVolunteer?._id, + assignments: [], + name: "Test Volunteer Group 1", + }); + + // add volunteer & group to event + await Event.updateOne( + { + _id: testEvent?._id, + }, + { + $push: { + volunteers: testVolunteer?._id, + volunteerGroups: testVolunteerGroup?._id, + }, + }, + ); + + // add group to volunteer + await EventVolunteer.updateOne( + { + _id: testVolunteer?._id, + }, + { + $push: { + groups: testVolunteerGroup?._id, + }, + }, + ); + + return [ + testUser, + testOrganization, + testEvent, + testVolunteer, + testVolunteerGroup, + ]; +}; + +export const createVolunteerAndActions = async (): Promise< + [ + TestOrganizationType, + TestEventType, + TestUserType, + TestUserType, + TestVolunteerType, + TestVolunteerType, + TestVolunteerGroupType, + TestActionItemType, + TestActionItemType, + ] +> => { + const [testUser, testOrganization] = await createTestUserAndOrganization(); + const testUser2 = await createTestUser(); + + const randomUser = await createTestUser(); + + const testEvent = await Event.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + allDay: true, + startDate: new Date(), + recurring: false, + isPublic: true, + isRegisterable: true, + creatorId: testUser?._id, + admins: [testUser?._id], + organization: testOrganization?._id, + volunteers: [], + volunteerGroups: [], + }); + + const today = new Date(); + const yesterday = new Date(today); + yesterday.setDate(today.getDate() - 1); + const twoWeeksAgo = new Date(today); + twoWeeksAgo.setDate(today.getDate() - 14); + const twoMonthsAgo = new Date(today); + twoMonthsAgo.setMonth(today.getMonth() - 2); + const twoYearsAgo = new Date(today); + twoYearsAgo.setFullYear(today.getFullYear() - 2); + + const testVolunteer1 = await EventVolunteer.create({ + creator: randomUser?._id, + event: testEvent?._id, + user: testUser?._id, + groups: [], + assignments: [], + hasAccepted: true, + hoursVolunteered: 10, + hoursHistory: [ + { + hours: 2, + date: yesterday, + }, + { + hours: 4, + date: twoWeeksAgo, + }, + { + hours: 2, + date: twoMonthsAgo, + }, + { + hours: 2, + date: twoYearsAgo, + }, + ], + }); + + const testVolunteer2 = await EventVolunteer.create({ + creator: randomUser?._id, + event: testEvent?._id, + user: testUser2?._id, + groups: [], + assignments: [], + hasAccepted: true, + hoursVolunteered: 8, + hoursHistory: [ + { + hours: 1, + date: yesterday, + }, + { + hours: 2, + date: twoWeeksAgo, + }, + { + hours: 3, + date: twoMonthsAgo, + }, + { + hours: 2, + date: twoYearsAgo, + }, + ], + }); + + // create a volunteer group with testVolunteer1 as a member & leader + const testVolunteerGroup = await EventVolunteerGroup.create({ + creator: randomUser?._id, + event: testEvent?._id, + volunteers: [testVolunteer1?._id, testVolunteer2?._id], + leader: testUser?._id, + assignments: [], + name: "Test Volunteer Group 1", + }); + + // add volunteer & group to event + await Event.updateOne( + { + _id: testEvent?._id, + }, + { + $addToSet: { + volunteers: { $each: [testVolunteer1?._id, testVolunteer2?._id] }, + volunteerGroups: testVolunteerGroup?._id, + }, + }, + ); + + const testActionItemCategory = await ActionItemCategory.create({ + creatorId: randomUser?._id, + organizationId: testOrganization?._id, + name: "Test Action Item Category 1", + isDisabled: false, + }); + + const testActionItem1 = await ActionItem.create({ + creator: randomUser?._id, + assigner: randomUser?._id, + assignee: testVolunteer1?._id, + assigneeType: "EventVolunteer", + assigneeGroup: null, + assigneeUser: null, + actionItemCategory: testActionItemCategory?._id, + event: testEvent?._id, + organization: testOrganization?._id, + allottedHours: 2, + assignmentDate: new Date(), + dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), + isCompleted: false, + }); + + const testActionItem2 = await ActionItem.create({ + creator: randomUser?._id, + assigner: randomUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: testVolunteerGroup?._id, + assignee: null, + assigneeUser: null, + actionItemCategory: testActionItemCategory?._id, + event: testEvent?._id, + organization: testOrganization?._id, + allottedHours: 4, + assignmentDate: new Date(), + dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 2000), + isCompleted: false, + }); + + await EventVolunteer.findByIdAndUpdate(testVolunteer1?._id, { + $push: { + assignments: testActionItem1?._id, + }, + }); + + await EventVolunteer.updateMany( + { _id: { $in: [testVolunteer1?._id, testVolunteer2?._id] } }, + { + $push: { + groups: testVolunteerGroup?._id, + assignments: testActionItem2?._id, + }, + }, + ); + + await EventVolunteerGroup.findByIdAndUpdate(testVolunteerGroup?._id, { + $addToSet: { assignments: testActionItem2 }, + }); + + return [ + testOrganization, + testEvent, + testUser, + testUser2, + testVolunteer1, + testVolunteer2, + testVolunteerGroup, + testActionItem1, + testActionItem2, + ]; +}; diff --git a/tests/middleware/fileUpload.spec.ts b/tests/middleware/fileUpload.spec.ts new file mode 100644 index 0000000000..5cdd0d7ed6 --- /dev/null +++ b/tests/middleware/fileUpload.spec.ts @@ -0,0 +1,215 @@ +import { describe, test, expect, vi, beforeEach } from "vitest"; +import type { Request, Response } from "express"; +import express from "express"; +import request from "supertest"; + +import { upload } from "../../src/config/multer"; +import { fileUpload } from "../../src/middleware"; +import { + CONTENT_TYPE_SHOULD_BE_MULTIPART_FORM_DATA, + FILE_SIZE_EXCEEDED, + IMAGE_SIZE_LIMIT, + INVALID_FILE_FIELD_NAME, + VIDEO_SIZE_LIMIT, +} from "../../src/constants"; + +vi.mock("../../src/libraries/requestContext", () => ({ + translate: (message: string): string => message, +})); + +describe("fileUpload Middleware", () => { + let app: express.Application; + + beforeEach(() => { + // Reset mocks + vi.clearAllMocks(); + + // Create new Express app for each test + app = express(); + + // Add json and urlencoded middleware + app.use(express.json()); + app.use(express.urlencoded({ extended: true })); + + // Add test route with the middleware + app.post("/upload", fileUpload("file"), (_req: Request, res: Response) => { + res.status(200).json({ message: "Upload successful" }); + }); + }); + + test("should reject requests without multipart/form-data content type", async () => { + const response = await request(app) + .post("/upload") + .set("Content-Type", "application/json") + .send({ data: "test" }); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: CONTENT_TYPE_SHOULD_BE_MULTIPART_FORM_DATA.MESSAGE, + }); + }); + + test("should reject request with no file", async () => { + const imageBuffer = Buffer.from("fake image content"); + const response = await request(app) + .post("/upload") + .set("Content-Type", "multipart/form-data") + .field("someField", "someValue") + .attach("different-file-field-name", imageBuffer, { + filename: "test.jpg", + contentType: "image/jpeg", + }); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: INVALID_FILE_FIELD_NAME.MESSAGE, + }); + }); + + test("should accept valid image upload", async () => { + // Create a small buffer to simulate an image file + const imageBuffer = Buffer.from("fake image content"); + + const response = await request(app) + .post("/upload") + .attach("file", imageBuffer, { + filename: "test.jpg", + contentType: "image/jpeg", + }); + + expect(response.status).toBe(200); + expect(response.body).toEqual({ + message: "Upload successful", + }); + }); + + test("should accept valid video upload", async () => { + // Create a small buffer to simulate a video file + const videoBuffer = Buffer.from("fake video content"); + + const response = await request(app) + .post("/upload") + .attach("file", videoBuffer, { + filename: "test.mp4", + contentType: "video/mp4", + }); + + expect(response.status).toBe(200); + expect(response.body).toEqual({ + message: "Upload successful", + }); + }); + + test("should reject image exceeding size limit", async () => { + const largeImageBuffer = Buffer.alloc(IMAGE_SIZE_LIMIT + 1); + + const response = await request(app) + .post("/upload") + .attach("file", largeImageBuffer, { + filename: "large.jpg", + contentType: "image/jpeg", + }); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: FILE_SIZE_EXCEEDED.MESSAGE, + description: "Image size exceeds the limit of 5MB", + }); + }); + + test("should reject video exceeding size limit", async () => { + const largeVideoBuffer = Buffer.alloc(VIDEO_SIZE_LIMIT + 1); + + const response = await request(app) + .post("/upload") + .attach("file", largeVideoBuffer, { + filename: "large.mp4", + contentType: "video/mp4", + }); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: FILE_SIZE_EXCEEDED.MESSAGE, + description: "Video size exceeds the limit of 50MB", + }); + }); + + test("should throw error on exceeding the multer max file size", async () => { + const largeVideoBuffer = Buffer.alloc(VIDEO_SIZE_LIMIT + 3); + + const response = await request(app) + .post("/upload") + .attach("file", largeVideoBuffer, { + filename: "large.mp4", + contentType: "video/mp4", + }); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: "File too large", + }); + }); + + test("should handle multiple files correctly", async () => { + const imageBuffer = Buffer.from("fake image content"); + + const response = await request(app) + .post("/upload") + .attach("file", imageBuffer, "test1.jpg") + .attach("anotherFile", imageBuffer, "test2.jpg"); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: INVALID_FILE_FIELD_NAME.MESSAGE, + }); + }); + + test("should accept request with no file when content-type is correct", async () => { + const response = await request(app) + .post("/upload") + .set("Content-Type", "multipart/form-data") + .field("someField", "someValue"); + + expect(response.status).toBe(200); + expect(response.body).toEqual({ + message: "Upload successful", + }); + }); + + test("should reject files with wrong field name", async () => { + const imageBuffer = Buffer.from("fake image content"); + + const response = await request(app) + .post("/upload") + .attach("wrongField", imageBuffer, "test.jpg"); + + expect(response.status).toBe(400); + expect(response.body).toEqual({ + error: INVALID_FILE_FIELD_NAME.MESSAGE, + }); + }); + + test("should handle generic upload errors", async () => { + const multerMock = vi.spyOn(upload, "single").mockImplementation(() => { + return (req, res, next): void => { + next(new Error("Generic upload error")); + }; + }); + + const imageBuffer = Buffer.from("fake image content"); + + const response = await request(app) + .post("/upload") + .attach("file", imageBuffer, { + filename: "test.jpg", + contentType: "image/jpeg", + }); + + expect(response.status).toBe(500); + expect(response.body).toEqual({ + error: "File upload failed", + }); + + multerMock.mockRestore(); + }); +}); diff --git a/tests/middleware/isAuth.spec.ts b/tests/middleware/isAuth.spec.ts index 78f685ca43..90a73c88ca 100644 --- a/tests/middleware/isAuth.spec.ts +++ b/tests/middleware/isAuth.spec.ts @@ -1,10 +1,18 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { Request } from "express"; -import { isAuth } from "../../src/middleware/isAuth"; +import type { NextFunction, Request, Response } from "express"; +import type { InterfaceAuthenticatedRequest } from "../../src/middleware/isAuth"; +import { isAuth, isAuthMiddleware } from "../../src/middleware/isAuth"; import { beforeEach, afterEach, describe, expect, it, vi } from "vitest"; import jwt from "jsonwebtoken"; import { logger } from "../../src/libraries/logger"; -import { ACCESS_TOKEN_SECRET } from "../../src/constants"; +import { + ACCESS_TOKEN_SECRET, + UNAUTHENTICATED_ERROR, +} from "../../src/constants"; + +vi.mock("../../src/libraries/requestContext", () => ({ + translate: (message: string): string => message, +})); interface TestInterfaceAuthData { isAuth: boolean; @@ -197,3 +205,69 @@ describe("middleware -> isAuth", () => { expect(authData).toEqual(testAuthData); }); }); + +describe("isAuthMiddleware", () => { + let mockRequest: Partial; + let mockResponse: Partial; + let nextFunction: NextFunction; + + beforeEach(() => { + mockRequest = { + headers: {}, + }; + mockResponse = { + status: vi.fn().mockReturnThis(), + json: vi.fn(), + } as unknown as Response; + nextFunction = vi.fn(); + + vi.clearAllMocks(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("should call next() when user is authenticated", () => { + // Mock successful token verification + vi.spyOn(jwt, "verify").mockImplementationOnce((...args: any) => { + const decoded = { + userId: "ValidUserId", + }; + const callBackFn = args[2]; + return callBackFn(null, decoded); + }); + + mockRequest.headers = { + authorization: "Bearer validToken", + }; + + isAuthMiddleware( + mockRequest as Request, + mockResponse as Response, + nextFunction, + ); + + expect(nextFunction).toHaveBeenCalled(); + expect(mockRequest.isAuth).toBe(true); + expect(mockRequest.userId).toBe("ValidUserId"); + expect(mockRequest.tokenExpired).toBeUndefined(); + expect(mockResponse.status).not.toHaveBeenCalled(); + expect(mockResponse.json).not.toHaveBeenCalled(); + }); + + it("should return 401 when token is not present", () => { + isAuthMiddleware( + mockRequest as Request, + mockResponse as Response, + nextFunction, + ); + + expect(nextFunction).not.toHaveBeenCalled(); + expect(mockResponse.status).toHaveBeenCalledWith(401); + expect(mockResponse.json).toHaveBeenCalledWith({ + message: UNAUTHENTICATED_ERROR.MESSAGE, + expired: undefined, + }); + }); +}); diff --git a/tests/resolvers/Chat/admins.spec.ts b/tests/resolvers/Chat/admins.spec.ts new file mode 100644 index 0000000000..00b752b622 --- /dev/null +++ b/tests/resolvers/Chat/admins.spec.ts @@ -0,0 +1,42 @@ +import "dotenv/config"; +import { admins as adminsResolver } from "../../../src/resolvers/Chat/admins"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { User } from "../../../src/models"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; + +let testChat: TestChatType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [, , testChat] = await createTestChatMessage(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Chat -> admins", () => { + it(`resolves the correct admin users for the given chat`, async () => { + const parent = testChat?.toObject(); + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (!adminsResolver) { + throw new Error("adminsResolver is not defined."); + } + const usersPayload = await adminsResolver(parent, {}, {}); + + const users = await User.find({ + _id: { + $in: testChat?.admins, + }, + }).lean(); + + expect(usersPayload).toEqual(users); + }); +}); diff --git a/tests/resolvers/DirectChat/creator.spec.ts b/tests/resolvers/Chat/creator.spec.ts similarity index 65% rename from tests/resolvers/DirectChat/creator.spec.ts rename to tests/resolvers/Chat/creator.spec.ts index ace3d79c36..4a1554d00d 100644 --- a/tests/resolvers/DirectChat/creator.spec.ts +++ b/tests/resolvers/Chat/creator.spec.ts @@ -1,28 +1,28 @@ import "dotenv/config"; -import { creator as creatorResolver } from "../../../src/resolvers/DirectChat/creator"; +import { creator as creatorResolver } from "../../../src/resolvers/Chat/creator"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { User } from "../../../src/models"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChat } from "../../helpers/directChat"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChat } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChat(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChat(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> creator", () => { +describe("resolvers -> Chat -> creator", () => { it(`returns user object for parent.creator`, async () => { - const parent = testDirectChat?.toObject(); + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } @@ -30,7 +30,7 @@ describe("resolvers -> DirectChat -> creator", () => { const creatorPayload = await creatorResolver?.(parent, {}, {}); const creator = await User.findOne({ - _id: testDirectChat?.creatorId, + _id: testChat?.creatorId, }).lean(); expect(creatorPayload).toEqual(creator); diff --git a/tests/resolvers/DirectChat/messages.spec.ts b/tests/resolvers/Chat/messages.spec.ts similarity index 57% rename from tests/resolvers/DirectChat/messages.spec.ts rename to tests/resolvers/Chat/messages.spec.ts index fb1632b790..05875ce534 100644 --- a/tests/resolvers/DirectChat/messages.spec.ts +++ b/tests/resolvers/Chat/messages.spec.ts @@ -1,37 +1,37 @@ import "dotenv/config"; -import { messages as messagesResolver } from "../../../src/resolvers/DirectChat/messages"; +import { messages as messagesResolver } from "../../../src/resolvers/Chat/messages"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import { DirectChatMessage } from "../../../src/models"; +import { ChatMessage } from "../../../src/models"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChatMessage(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> messages", () => { +describe("resolvers -> Chat -> messages", () => { it(`returns user object for parent.messages`, async () => { - const parent = testDirectChat?.toObject(); + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } const messagesPayload = await messagesResolver?.(parent, {}, {}); - const messages = await DirectChatMessage.find({ + const messages = await ChatMessage.find({ _id: { - $in: testDirectChat?.messages, + $in: testChat?.messages, }, }).lean(); diff --git a/tests/resolvers/DirectChat/organization.spec.ts b/tests/resolvers/Chat/organization.spec.ts similarity index 61% rename from tests/resolvers/DirectChat/organization.spec.ts rename to tests/resolvers/Chat/organization.spec.ts index 70d8c99476..f8414b6a74 100644 --- a/tests/resolvers/DirectChat/organization.spec.ts +++ b/tests/resolvers/Chat/organization.spec.ts @@ -1,28 +1,28 @@ import "dotenv/config"; +import { organization as organizationResolver } from "../../../src/resolvers/Chat/organization"; +import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; -import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { Organization } from "../../../src/models"; -import { organization as organizationResolver } from "../../../src/resolvers/DirectChat/organization"; -import { connect, disconnect } from "../../helpers/db"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChat } from "../../helpers/directChat"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChat(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> organization", () => { - it(`returns user object for parent.organization`, async () => { - const parent = testDirectChat?.toObject(); +describe("resolvers -> Chat -> organization", () => { + it(`resolves the correct organization for the given chat`, async () => { + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } @@ -30,22 +30,22 @@ describe("resolvers -> DirectChat -> organization", () => { const organizationPayload = await organizationResolver?.(parent, {}, {}); const organization = await Organization.findOne({ - _id: testDirectChat?.organization, + _id: testChat?.organization, }).lean(); expect(organizationPayload).toEqual(organization); }); - - it(`returns user object for parent.organization`, async () => { - const parent = testDirectChat?.toObject(); + it("resolves the organization from cache", async () => { + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } + // Simulate the cache resolution logic here (if applicable) const organizationPayload = await organizationResolver?.(parent, {}, {}); const organization = await Organization.findOne({ - _id: testDirectChat?.organization, + _id: testChat?.organization, }).lean(); expect(organizationPayload).toEqual(organization); diff --git a/tests/resolvers/DirectChat/users.spec.ts b/tests/resolvers/Chat/users.spec.ts similarity index 59% rename from tests/resolvers/DirectChat/users.spec.ts rename to tests/resolvers/Chat/users.spec.ts index d30e6fa4cd..541b02b497 100644 --- a/tests/resolvers/DirectChat/users.spec.ts +++ b/tests/resolvers/Chat/users.spec.ts @@ -1,28 +1,28 @@ import "dotenv/config"; -import { users as usersResolver } from "../../../src/resolvers/DirectChat/users"; +import { users as usersResolver } from "../../../src/resolvers/Chat/users"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { User } from "../../../src/models"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; -let testDirectChat: TestDirectChatType; +let testChat: TestChatType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const userOrgChat = await createTestDirectChatMessage(); - testDirectChat = userOrgChat[2]; + const userOrgChat = await createTestChatMessage(); + testChat = userOrgChat[2]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChat -> users", () => { +describe("resolvers -> Chat -> users", () => { it(`returns user object for parent.users`, async () => { - const parent = testDirectChat?.toObject(); + const parent = testChat?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } @@ -31,7 +31,7 @@ describe("resolvers -> DirectChat -> users", () => { const users = await User.find({ _id: { - $in: testDirectChat?.users, + $in: testChat?.users, }, }).lean(); diff --git a/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts new file mode 100644 index 0000000000..bba2b832f5 --- /dev/null +++ b/tests/resolvers/ChatMessage/chatMessageBelongsTo.spec.ts @@ -0,0 +1,76 @@ +import "dotenv/config"; +import { chatMessageBelongsTo as chatMessageBelongsToResolver } from "../../../src/resolvers/ChatMessage/chatMessageBelongsTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { Chat } from "../../../src/models"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; +import { Types } from "mongoose"; +import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; + +let testChatMessage: TestChatMessageType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const temp = await createTestChatMessage(); + testChatMessage = temp[3]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> ChatMessage -> chatMessageBelongsTo", () => { + it(`returns chat object for parent.chatMessageBelongsTo`, async () => { + const parent = testChatMessage?.toObject(); + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof chatMessageBelongsToResolver !== "function") { + throw new Error("chatMessageBelongsToResolver is not a function."); + } + + const chatMessageBelongsToPayload = await chatMessageBelongsToResolver( + parent, + {}, + {}, + ); + + const chatMessageBelongsTo = await Chat.findOne({ + _id: testChatMessage?.chatMessageBelongsTo, + }).lean(); + + expect(chatMessageBelongsToPayload).toEqual(chatMessageBelongsTo); + }); + it(`throws NotFoundError if no chat exists`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message: string) => message); + + const parent = { + ...testChatMessage?.toObject(), + chatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId + }; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof chatMessageBelongsToResolver !== "function") { + throw new Error("chatMessageBelongsToResolver is not a function."); + } + + try { + // @ts-expect-error - Testing for error + await chatMessageBelongsToResolver(parent, {}, {}); + } catch (error: unknown) { + expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); + } + }); +}); diff --git a/tests/resolvers/ChatMessage/replyTo.spec.ts b/tests/resolvers/ChatMessage/replyTo.spec.ts new file mode 100644 index 0000000000..585fd09b7e --- /dev/null +++ b/tests/resolvers/ChatMessage/replyTo.spec.ts @@ -0,0 +1,119 @@ +import "dotenv/config"; +import { replyTo as replyToResolver } from "../../../src/resolvers/ChatMessage/replyTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { ChatMessage } from "../../../src/models"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { + createTestChatMessageWithoutReply, + createTestChatMessage, +} from "../../helpers/chat"; +import { Types } from "mongoose"; +import { MESSAGE_NOT_FOUND_ERROR } from "../../../src/constants"; + +let testChatMessage: TestChatMessageType; +let testChatMessageWithoutReply: TestChatMessageType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + try { + MONGOOSE_INSTANCE = await connect(); + } catch (error) { + console.error("Failed to connect to the database", error); + throw error; + } + + try { + const temp1 = await createTestChatMessage(); + testChatMessage = temp1[3]; + } catch (error) { + console.error("Failed to create test chat message", error); + throw error; + } + + try { + const temp = await createTestChatMessageWithoutReply(); + testChatMessageWithoutReply = temp[3]; + } catch (error) { + console.error("Failed to create test chat message without reply", error); + throw error; + } +}); + +afterAll(async () => { + if (MONGOOSE_INSTANCE) { + await disconnect(MONGOOSE_INSTANCE); + } +}); + +describe("resolvers -> ChatMessage -> replyTo", () => { + it(`returns chat object for parent.replyTo`, async () => { + const parent = testChatMessage ? testChatMessage.toObject() : null; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + try { + const replyToPayload = await replyToResolver(parent, {}, {}); + const replyTo = await ChatMessage.findOne({ + _id: testChatMessage?.replyTo, + }).lean(); + expect(replyToPayload).toEqual(replyTo); + } catch (error) { + console.error("Test failed", error); + throw error; + } + }); + it(`throws NotFoundError if no chat exists`, async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message: string) => message); + + const parent = { + ...testChatMessage?.toObject(), + replyTo: new Types.ObjectId(), // Set to a non-existing ObjectId + }; + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + try { + // @ts-expect-error - Testing for error + await replyToResolver(parent, {}, {}); + } catch (error: unknown) { + expect(spy).toBeCalledWith(MESSAGE_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(MESSAGE_NOT_FOUND_ERROR.MESSAGE); + } finally { + spy.mockRestore(); // Restore the original function + } + }); + it(`return null if no replyTo`, async () => { + const parent = testChatMessageWithoutReply?.toObject(); + + if (!parent) { + throw new Error("Parent object is undefined."); + } + + if (typeof replyToResolver !== "function") { + throw new Error("replyToResolver is not a function."); + } + + const replyToPayload = await replyToResolver(parent, {}, {}); + + const replyTo = null; + + expect(replyToPayload).toEqual(replyTo); + }); +}); diff --git a/tests/resolvers/DirectChatMessage/sender.spec.ts b/tests/resolvers/ChatMessage/sender.spec.ts similarity index 53% rename from tests/resolvers/DirectChatMessage/sender.spec.ts rename to tests/resolvers/ChatMessage/sender.spec.ts index 399de17579..8c64c91c08 100644 --- a/tests/resolvers/DirectChatMessage/sender.spec.ts +++ b/tests/resolvers/ChatMessage/sender.spec.ts @@ -1,37 +1,37 @@ import "dotenv/config"; -import { sender as senderResolver } from "../../../src/resolvers/DirectChatMessage/sender"; +import { sender as senderResolver } from "../../../src/resolvers/ChatMessage/sender"; import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { User } from "../../../src/models"; import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; import { Types } from "mongoose"; import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; -let testDirectChatMessage: TestDirectChatMessageType; +let testChatMessage: TestChatMessageType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChatMessage(); - testDirectChatMessage = temp[3]; + const temp = await createTestChatMessage(); + testChatMessage = temp[3]; }); afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> DirectChatMessage -> sender", () => { +describe("resolvers -> ChatMessage -> sender", () => { it(`returns user object for parent.sender`, async () => { - const parent = testDirectChatMessage?.toObject(); + const parent = testChatMessage?.toObject(); if (!parent) { throw new Error("Parent object is undefined."); } const senderPayload = await senderResolver?.(parent, {}, {}); const sender = await User.findOne({ - _id: testDirectChatMessage?.sender, + _id: testChatMessage?.sender, }).lean(); expect(senderPayload).toEqual(sender); @@ -41,23 +41,25 @@ describe("resolvers -> DirectChatMessage -> sender", () => { const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); - const parent = { - ...testDirectChatMessage?.toObject(), - sender: new Types.ObjectId(), // Set to a non-existing ObjectId - }; + if (testChatMessage?._id) { + const parent = { + ...testChatMessage?.toObject(), + _id: testChatMessage._id, + sender: new Types.ObjectId(), // Set to a non-existing ObjectId + }; - if (!parent) { - throw new Error("Parent object is undefined."); - } + if (!parent) { + throw new Error("Parent object is undefined."); + } - try { - if (senderResolver) { - // @ts-expect-error - Testing for error - await senderResolver(parent, {}, {}); + try { + if (senderResolver) { + await senderResolver(parent, {}, {}); + } + } catch (error: unknown) { + expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } }); }); diff --git a/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts b/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts deleted file mode 100644 index 5ff19d843e..0000000000 --- a/tests/resolvers/DirectChatMessage/directChatMessageBelongsTo.spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -import "dotenv/config"; -import { directChatMessageBelongsTo as directChatMessageBelongsToResolver } from "../../../src/resolvers/DirectChatMessage/directChatMessageBelongsTo"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { DirectChat } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; -import { Types } from "mongoose"; -import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testDirectChatMessage: TestDirectChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChatMessage(); - testDirectChatMessage = temp[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> DirectChatMessage -> directChatMessageBelongsTo", () => { - it(`returns directChat object for parent.directChatMessageBelongsTo`, async () => { - const parent = testDirectChatMessage?.toObject(); - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - if (typeof directChatMessageBelongsToResolver !== "function") { - throw new Error("directChatMessageBelongsToResolver is not a function."); - } - - const directChatMessageBelongsToPayload = - await directChatMessageBelongsToResolver(parent, {}, {}); - - const directChatMessageBelongsTo = await DirectChat.findOne({ - _id: testDirectChatMessage?.directChatMessageBelongsTo, - }).lean(); - - expect(directChatMessageBelongsToPayload).toEqual( - directChatMessageBelongsTo, - ); - }); - it(`throws NotFoundError if no directChat exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testDirectChatMessage?.toObject(), - directChatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - if (typeof directChatMessageBelongsToResolver !== "function") { - throw new Error("directChatMessageBelongsToResolver is not a function."); - } - - try { - // @ts-expect-error - Testing for error - await directChatMessageBelongsToResolver(parent, {}, {}); - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/DirectChatMessage/receiver.spec.ts b/tests/resolvers/DirectChatMessage/receiver.spec.ts deleted file mode 100644 index 9c39f6b18b..0000000000 --- a/tests/resolvers/DirectChatMessage/receiver.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import "dotenv/config"; -import { receiver as receiverResolver } from "../../../src/resolvers/DirectChatMessage/receiver"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { User } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; -import { Types } from "mongoose"; -import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testDirectChatMessage: TestDirectChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChatMessage(); - testDirectChatMessage = temp[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> DirectChatMessage -> receiver", () => { - it(`returns user object for parent.receiver`, async () => { - const parent = testDirectChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const receiverPayload = await receiverResolver?.(parent, {}, {}); - - const receiver = await User.findOne({ - _id: testDirectChatMessage?.receiver, - }).lean(); - - expect(receiverPayload).toEqual(receiver); - }); - it(`throws NotFoundError if no user exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testDirectChatMessage?.toObject(), - receiver: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (receiverResolver) { - // @ts-expect-error - Testing for error - await receiverResolver(parent, {}, {}); - } - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/Event/actionItems.spec.ts b/tests/resolvers/Event/actionItems.spec.ts index 716f511d96..ad06fbb673 100644 --- a/tests/resolvers/Event/actionItems.spec.ts +++ b/tests/resolvers/Event/actionItems.spec.ts @@ -26,7 +26,7 @@ describe("resolvers -> Organization -> actionItems", () => { const actionItemsPayload = await actionItemsResolver?.(parent, {}, {}); const actionItems = await ActionItem.find({ - eventId: testEvent?._id, + event: testEvent?._id, }).lean(); expect(actionItemsPayload).toEqual(actionItems); diff --git a/tests/resolvers/EventVolunteer/creator.spec.ts b/tests/resolvers/EventVolunteer/creator.spec.ts deleted file mode 100644 index 88e07a8722..0000000000 --- a/tests/resolvers/EventVolunteer/creator.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import "dotenv/config"; -import { creator as creatorResolver } from "../../../src/resolvers/EventVolunteer/creator"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - beforeEach, - vi, -} from "vitest"; -import type { TestEventVolunteerType } from "../../helpers/events"; -import { createTestEventAndVolunteer } from "../../helpers/events"; -import type { TestUserType } from "../../helpers/userAndOrg"; -import type { InterfaceEventVolunteer } from "../../../src/models"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testEventVolunteer: TestEventVolunteerType; -let creatorUser: TestUserType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [, creatorUser, , testEventVolunteer] = await createTestEventAndVolunteer(); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> creator", () => { - beforeEach(() => { - vi.resetModules(); - }); - it(`returns the correct creator object for parent event volunteer`, async () => { - const parent = testEventVolunteer?.toObject(); - const creatorPayload = await creatorResolver?.( - parent as InterfaceEventVolunteer, - {}, - {}, - ); - - expect(creatorPayload?._id).toEqual(creatorUser?._id); - }); -}); diff --git a/tests/resolvers/EventVolunteer/event.spec.ts b/tests/resolvers/EventVolunteer/event.spec.ts deleted file mode 100644 index 7a0b04ab5b..0000000000 --- a/tests/resolvers/EventVolunteer/event.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import "dotenv/config"; -import { event as eventResolver } from "../../../src/resolvers/EventVolunteer/event"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { - TestEventType, - TestEventVolunteerType, -} from "../../helpers/events"; -import { createTestEventAndVolunteer } from "../../helpers/events"; -import type { InterfaceEventVolunteer } from "../../../src/models"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testEvent: TestEventType; -let testEventVolunteer: TestEventVolunteerType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [, , testEvent, testEventVolunteer] = await createTestEventAndVolunteer(); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> event", () => { - it(`returns the correct event object for parent event volunteer`, async () => { - const parent = testEventVolunteer?.toObject(); - - const eventPayload = await eventResolver?.( - parent as InterfaceEventVolunteer, - {}, - {}, - ); - - expect(eventPayload).toEqual(testEvent?.toObject()); - }); -}); diff --git a/tests/resolvers/EventVolunteer/group.spec.ts b/tests/resolvers/EventVolunteer/group.spec.ts deleted file mode 100644 index 856641b624..0000000000 --- a/tests/resolvers/EventVolunteer/group.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import "dotenv/config"; -import { group as groupResolver } from "../../../src/resolvers/EventVolunteer/group"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - beforeEach, - vi, -} from "vitest"; -import type { - TestEventType, - TestEventVolunteerType, -} from "../../helpers/events"; -import { createTestEvent } from "../../helpers/events"; -import type { TestUserType } from "../../helpers/userAndOrg"; -import type { InterfaceEventVolunteer } from "../../../src/models"; -import { EventVolunteer, EventVolunteerGroup } from "../../../src/models"; -import type { TestEventVolunteerGroupType } from "../Mutation/createEventVolunteer.spec"; -import { createTestUser } from "../../helpers/user"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testEventVolunteer: TestEventVolunteerType; -let eventAdminUser: TestUserType; -let testUser: TestUserType; -let testEvent: TestEventType; -let testGroup: TestEventVolunteerGroupType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [eventAdminUser, , testEvent] = await createTestEvent(); - testUser = await createTestUser(); - testGroup = await EventVolunteerGroup.create({ - name: "test", - creatorId: eventAdminUser?._id, - leaderId: eventAdminUser?._id, - eventId: testEvent?._id, - }); - testEventVolunteer = await EventVolunteer.create({ - eventId: testEvent?._id, - userId: testUser?._id, - creatorId: eventAdminUser?._id, - groupId: testGroup?._id, - isAssigned: false, - isInvited: true, - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> group", () => { - beforeEach(() => { - vi.resetModules(); - }); - it(`returns the correct event volunteer group object for parent event volunteer`, async () => { - const parent = testEventVolunteer?.toObject(); - const groupPayload = await groupResolver?.( - parent as InterfaceEventVolunteer, - {}, - {}, - ); - console.log(groupPayload); - console.log(testGroup); - - expect(groupPayload?._id).toEqual(testGroup?._id); - }); -}); diff --git a/tests/resolvers/EventVolunteer/user.spec.ts b/tests/resolvers/EventVolunteer/user.spec.ts deleted file mode 100644 index 56ac382f6b..0000000000 --- a/tests/resolvers/EventVolunteer/user.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import "dotenv/config"; -import { user as userResolver } from "../../../src/resolvers/EventVolunteer/user"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - beforeEach, - vi, -} from "vitest"; -import type { TestEventVolunteerType } from "../../helpers/events"; -import { createTestEventAndVolunteer } from "../../helpers/events"; -import type { TestUserType } from "../../helpers/userAndOrg"; -import type { InterfaceEventVolunteer } from "../../../src/models"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testEventVolunteer: TestEventVolunteerType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [testUser, , , testEventVolunteer] = await createTestEventAndVolunteer(); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> user", () => { - beforeEach(() => { - vi.resetModules(); - }); - it(`returns the correct user object for parent event volunteer`, async () => { - const parent = testEventVolunteer?.toObject(); - console.log(testEventVolunteer?.userId); - console.log(testUser?._id); - - const userPayload = await userResolver?.( - parent as InterfaceEventVolunteer, - {}, - {}, - ); - - expect(userPayload).toEqual({ - ...testUser?.toObject(), - updatedAt: expect.anything(), - }); - }); -}); diff --git a/tests/resolvers/EventVolunteerGroup/creator.spec.ts b/tests/resolvers/EventVolunteerGroup/creator.spec.ts deleted file mode 100644 index e9bd6502bf..0000000000 --- a/tests/resolvers/EventVolunteerGroup/creator.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import "dotenv/config"; -import { creator as creatorResolver } from "../../../src/resolvers/EventVolunteerGroup/creator"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestEventType } from "../../helpers/events"; -import { createTestEvent } from "../../helpers/events"; -import type { InterfaceEventVolunteerGroup } from "../../../src/models"; -import { EventVolunteerGroup } from "../../../src/models"; -import type { TestUserType } from "../../helpers/user"; -import type { TestEventVolunteerGroupType } from "../Mutation/createEventVolunteer.spec"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let eventAdminUser: TestUserType; -let testEvent: TestEventType; -let testGroup: TestEventVolunteerGroupType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [eventAdminUser, , testEvent] = await createTestEvent(); - testGroup = await EventVolunteerGroup.create({ - name: "test", - creatorId: eventAdminUser?._id, - leaderId: eventAdminUser?._id, - eventId: testEvent?._id, - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> creator", () => { - it(`returns the correct creator user object for parent event volunteer group`, async () => { - const parent = testGroup?.toObject(); - - const creatorPayload = await creatorResolver?.( - parent as InterfaceEventVolunteerGroup, - {}, - {}, - ); - - expect(creatorPayload?._id).toEqual(eventAdminUser?._id); - }); -}); diff --git a/tests/resolvers/EventVolunteerGroup/event.spec.ts b/tests/resolvers/EventVolunteerGroup/event.spec.ts deleted file mode 100644 index 5cfaeb7450..0000000000 --- a/tests/resolvers/EventVolunteerGroup/event.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import "dotenv/config"; -import { event as eventResolver } from "../../../src/resolvers/EventVolunteerGroup/event"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestEventType } from "../../helpers/events"; -import { createTestEvent } from "../../helpers/events"; -import type { InterfaceEventVolunteerGroup } from "../../../src/models"; -import { EventVolunteerGroup } from "../../../src/models"; -import type { TestUserType } from "../../helpers/user"; -import type { TestEventVolunteerGroupType } from "../Mutation/createEventVolunteer.spec"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let eventAdminUser: TestUserType; -let testEvent: TestEventType; -let testGroup: TestEventVolunteerGroupType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [eventAdminUser, , testEvent] = await createTestEvent(); - testGroup = await EventVolunteerGroup.create({ - name: "test", - creatorId: eventAdminUser?._id, - leaderId: eventAdminUser?._id, - eventId: testEvent?._id, - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> event", () => { - it(`returns the correct event object for parent event volunteer group`, async () => { - const parent = testGroup?.toObject(); - - const eventPayload = await eventResolver?.( - parent as InterfaceEventVolunteerGroup, - {}, - {}, - ); - - expect(eventPayload).toEqual(testEvent?.toObject()); - }); -}); diff --git a/tests/resolvers/EventVolunteerGroup/leader.spec.ts b/tests/resolvers/EventVolunteerGroup/leader.spec.ts deleted file mode 100644 index 07481e41b5..0000000000 --- a/tests/resolvers/EventVolunteerGroup/leader.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import "dotenv/config"; -import { leader as leaderResolver } from "../../../src/resolvers/EventVolunteerGroup/leader"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestEventType } from "../../helpers/events"; -import { createTestEvent } from "../../helpers/events"; -import type { InterfaceEventVolunteerGroup } from "../../../src/models"; -import { EventVolunteerGroup } from "../../../src/models"; -import type { TestUserType } from "../../helpers/user"; -import type { TestEventVolunteerGroupType } from "../Mutation/createEventVolunteer.spec"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let eventAdminUser: TestUserType; -let testEvent: TestEventType; -let testGroup: TestEventVolunteerGroupType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [eventAdminUser, , testEvent] = await createTestEvent(); - testGroup = await EventVolunteerGroup.create({ - name: "test", - creatorId: eventAdminUser?._id, - leaderId: eventAdminUser?._id, - eventId: testEvent?._id, - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> EventVolunteer -> leader", () => { - it(`returns the correct leader user object for parent event volunteer group`, async () => { - const parent = testGroup?.toObject(); - - const leaderPayload = await leaderResolver?.( - parent as InterfaceEventVolunteerGroup, - {}, - {}, - ); - - expect(leaderPayload?._id).toEqual(eventAdminUser?._id); - }); -}); diff --git a/tests/resolvers/GroupChat/creator.spec.ts b/tests/resolvers/GroupChat/creator.spec.ts deleted file mode 100644 index 5184e618d4..0000000000 --- a/tests/resolvers/GroupChat/creator.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import "dotenv/config"; -import { creator as creatorResolver } from "../../../src/resolvers/GroupChat/creator"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import type { InterfaceGroupChat } from "../../../src/models"; -import { User } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> creator", () => { - it(`returns user object for parent.creator`, async () => { - const parent = testGroupChat?.toObject(); - - const creatorPayload = await creatorResolver?.( - parent ?? ({} as InterfaceGroupChat), - {}, - {}, - ); - - const creator = await User.findOne({ - _id: testGroupChat?.creatorId, - }).lean(); - - expect(creatorPayload).toEqual(creator); - }); -}); diff --git a/tests/resolvers/GroupChat/messages.spec.ts b/tests/resolvers/GroupChat/messages.spec.ts deleted file mode 100644 index 5f69793f0e..0000000000 --- a/tests/resolvers/GroupChat/messages.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import "dotenv/config"; -import { messages as messagesResolver } from "../../../src/resolvers/GroupChat/messages"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { GroupChatMessage } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> messages", () => { - it(`returns user objects for parent.messages`, async () => { - const parent = testGroupChat?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const messagesPayload = await messagesResolver?.(parent, {}, {}); - - const messages = await GroupChatMessage.find({ - _id: { - $in: testGroupChat?.messages, - }, - }).lean(); - - expect(messagesPayload).toEqual(messages); - }); -}); diff --git a/tests/resolvers/GroupChat/organization.spec.ts b/tests/resolvers/GroupChat/organization.spec.ts deleted file mode 100644 index 2cb0baee86..0000000000 --- a/tests/resolvers/GroupChat/organization.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import "dotenv/config"; -import { organization as organizationResolver } from "../../../src/resolvers/GroupChat/organization"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Organization } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> organization", () => { - it(`returns user objects for parent.organization`, async () => { - const parent = testGroupChat?.toObject(); - if (parent) { - const organizationPayload = await organizationResolver?.(parent, {}, {}); - const organization = await Organization.findOne({ - _id: testGroupChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); - } - }); - it(`returns user objects for parent.organization from cache`, async () => { - const parent = testGroupChat?.toObject(); - if (parent) { - const organizationPayload = await organizationResolver?.(parent, {}, {}); - const organization = await Organization.findOne({ - _id: testGroupChat?.organization, - }).lean(); - - expect(organizationPayload).toEqual(organization); - } - }); -}); diff --git a/tests/resolvers/GroupChat/users.spec.ts b/tests/resolvers/GroupChat/users.spec.ts deleted file mode 100644 index 8616ca5e1a..0000000000 --- a/tests/resolvers/GroupChat/users.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import "dotenv/config"; -import { users as usersResolver } from "../../../src/resolvers/GroupChat/users"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { User } from "../../../src/models"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChat -> users", () => { - it(`returns user objects for parent.users`, async () => { - const parent = testGroupChat?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const usersPayload = await usersResolver?.(parent, {}, {}); - - const users = await User.find({ - _id: { - $in: testGroupChat?.users, - }, - }).lean(); - - expect(usersPayload).toEqual(users); - }); -}); diff --git a/tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts b/tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts deleted file mode 100644 index 08ade6fde5..0000000000 --- a/tests/resolvers/GroupChatMessage/groupChatMessageBelongsTo.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import "dotenv/config"; -import { groupChatMessageBelongsTo as groupChatMessageBelongsToResolver } from "../../../src/resolvers/GroupChatMessage/groupChatMessageBelongsTo"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChat } from "../../../src/models"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import type { TestGroupChatMessageType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testGroupChatMessage: TestGroupChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChatMessage(); - testGroupChatMessage = resultArray[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChatMessage -> groupChatMessageBelongsTo", () => { - it(`returns groupChatMessageBelongsTo object for parent.groupChatMessageBelongsTo`, async () => { - const parent = testGroupChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const groupChatMessageBelongsToPayload = - await groupChatMessageBelongsToResolver?.(parent, {}, {}); - - const groupChatMessageBelongsTo = await GroupChat.findOne({ - _id: testGroupChatMessage?.groupChatMessageBelongsTo, - }).lean(); - - expect(groupChatMessageBelongsToPayload).toEqual(groupChatMessageBelongsTo); - }); - it(`throws NotFoundError if no groupChatMessageBelongsTo exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testGroupChatMessage?.toObject(), - groupChatMessageBelongsTo: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (groupChatMessageBelongsToResolver) { - // @ts-expect-error - Testing for error - await groupChatMessageBelongsToResolver(parent, {}, {}); - } - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/GroupChatMessage/sender.spec.ts b/tests/resolvers/GroupChatMessage/sender.spec.ts deleted file mode 100644 index d9c335d4e2..0000000000 --- a/tests/resolvers/GroupChatMessage/sender.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import "dotenv/config"; -import { sender as senderResolver } from "../../../src/resolvers/GroupChatMessage/sender"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { User } from "../../../src/models"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import type { TestGroupChatMessageType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { Types } from "mongoose"; -import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; - -let testGroupChatMessage: TestGroupChatMessageType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChatMessage(); - testGroupChatMessage = resultArray[3]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> GroupChatMessage -> sender", () => { - it(`returns sender object for parent.sender`, async () => { - const parent = testGroupChatMessage?.toObject(); - if (!parent) { - throw new Error("Parent object is undefined."); - } - const senderPayload = await senderResolver?.(parent, {}, {}); - - const sender = await User.findOne({ - _id: testGroupChatMessage?.sender, - }).lean(); - - expect(senderPayload).toEqual(sender); - }); - it(`throws NotFoundError if no user exists`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const parent = { - ...testGroupChatMessage?.toObject(), - sender: new Types.ObjectId(), // Set to a non-existing ObjectId - }; - - if (!parent) { - throw new Error("Parent object is undefined."); - } - - try { - if (senderResolver) { - // @ts-expect-error - Testing for error - await senderResolver(parent, {}, {}); - } - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); -}); diff --git a/tests/resolvers/Mutation/UpdateSessionTimeout.spec.ts b/tests/resolvers/Mutation/UpdateSessionTimeout.spec.ts new file mode 100644 index 0000000000..25ebe8855e --- /dev/null +++ b/tests/resolvers/Mutation/UpdateSessionTimeout.spec.ts @@ -0,0 +1,236 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; + +import { User, AppUserProfile, Community } from "../../../src/models"; +import type { MutationUpdateSessionTimeoutArgs } from "../../../src/types/generatedGraphQLTypes"; +import { connect, disconnect } from "../../helpers/db"; + +import { nanoid } from "nanoid"; +import { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + it, + vi, +} from "vitest"; +import { + COMMUNITY_NOT_FOUND_ERROR, + INVALID_TIMEOUT_RANGE, + USER_NOT_FOUND_ERROR, + APP_USER_PROFILE_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_SUPERADMIN, +} from "../../../src/constants"; +import { updateSessionTimeout as updateSessionTimeoutResolver } from "../../../src/resolvers/Mutation/updateSessionTimeout"; +import type { + TestAppUserProfileType, + TestUserType, +} from "../../helpers/userAndOrg"; + +import { requestContext } from "../../../src/libraries"; + +import bcrypt from "bcryptjs"; + +// Global variables to store mongoose instance and test user/appUserProfile +let MONGOOSE_INSTANCE: typeof mongoose; +let testUser: TestUserType; +let testAppUserProfile: TestAppUserProfileType; + +// Mock the uploadEncodedImage function used in the tests +vi.mock("../../utilities/uploadEncodedImage", () => ({ + uploadEncodedImage: vi.fn(), +})); + +// Mock bcrypt.hash to return a fixed value +vi.mock("bcrypt", () => ({ + hash: vi.fn().mockResolvedValue("mockedHashedPassword"), +})); + +/** + * Establishes a connection to the database before all tests. + */ +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); +}); + +/** + * Closes the database connection after all tests have completed. + */ +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +/** + * Sets up test data in the database before each test. + * Creates a test user and associated appUserProfile, and links them together. + * Also, creates a test community with a timeout value. + */ +beforeEach(async () => { + const hashedPassword = await bcrypt.hash("password", 12); + + testUser = await User.create({ + email: `email${nanoid().toLowerCase()}@gmail.com`, + password: hashedPassword, + firstName: "firstName", + lastName: "lastName", + }); + + testAppUserProfile = await AppUserProfile.create({ + userId: testUser._id, + appLanguageCode: "en", + tokenVersion: 0, + isSuperAdmin: true, + }); + + testUser.appUserProfileId = testAppUserProfile._id; + await testUser.save(); // Directly save the update to testUser + + await Community.create({ + name: "test community", + timeout: 25, + }); +}); + +/** + * Restores all mocks and resets modules after each test. + */ +afterEach(() => { + vi.restoreAllMocks(); + vi.doUnmock("../../../src/constants"); + vi.resetModules(); +}); + +/** + * Helper function to handle error assertions. + * @param resolverFunc - The resolver function to call + * @param args - The mutation arguments + * @param context - The request context + * @param expectedErrorMessage - The expected error message for assertion + */ +const assertThrowsErrorWithMessage = async ( + resolverFunc: typeof updateSessionTimeoutResolver, + args: MutationUpdateSessionTimeoutArgs, + context: { userId: string | undefined }, + expectedErrorMessage: string, +): Promise => { + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementation((message) => message); + + try { + await resolverFunc?.({}, args, context); + } catch (error: unknown) { + expect(spy).toHaveBeenCalledWith(expectedErrorMessage); + expect((error as Error).message).toEqual(expectedErrorMessage); + } +}; + +/** + * Test suite for the `updateSessionTimeout` resolver function. + */ +describe("resolvers -> Mutation -> updateSessionTimeout", () => { + it("returns error when attempting to update timeout for non-existent community", async () => { + const args: MutationUpdateSessionTimeoutArgs = { + timeout: 15, + }; + const context = { + userId: testUser?._id, + }; + + await Community.deleteMany({}).lean(); + + await assertThrowsErrorWithMessage( + updateSessionTimeoutResolver, + args, + context, + COMMUNITY_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("returns error when attempting to update timeout for non-existent user", async () => { + const args: MutationUpdateSessionTimeoutArgs = { + timeout: 15, + }; + const context = { + userId: new Types.ObjectId().toString(), + }; + + await assertThrowsErrorWithMessage( + updateSessionTimeoutResolver, + args, + context, + USER_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("returns error when appUserProfile is missing for the user", async () => { + const args: MutationUpdateSessionTimeoutArgs = { + timeout: 15, + }; + const context = { + userId: testUser?._id, + }; + + await AppUserProfile.deleteOne({ userId: testUser?._id }).lean(); + + await assertThrowsErrorWithMessage( + updateSessionTimeoutResolver, + args, + context, + APP_USER_PROFILE_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("returns validation error for timeout out of valid range", async () => { + const args: MutationUpdateSessionTimeoutArgs = { + timeout: 3, + }; + const context = { + userId: testUser?._id, + }; + + await assertThrowsErrorWithMessage( + updateSessionTimeoutResolver, + args, + context, + INVALID_TIMEOUT_RANGE.MESSAGE, + ); + }); + + it("returns unauthorized error when superAdmin is set to false", async () => { + const args: MutationUpdateSessionTimeoutArgs = { + timeout: 15, + }; + const context = { + userId: testUser?._id, + }; + + await AppUserProfile.findByIdAndUpdate( + { _id: testUser?.appUserProfileId }, + { isSuperAdmin: false }, + ).lean(); + + await assertThrowsErrorWithMessage( + updateSessionTimeoutResolver, + args, + context, + USER_NOT_AUTHORIZED_SUPERADMIN.MESSAGE, + ); + }); + + it("successfully updates session timeout when valid arguments are provided", async () => { + const args: MutationUpdateSessionTimeoutArgs = { + timeout: 15, + }; + const context = { + userId: testUser?._id, + }; + + const result = await updateSessionTimeoutResolver?.({}, args, context); + + expect(result).toEqual(true); + }); +}); diff --git a/tests/resolvers/Mutation/addEventAttendee.spec.ts b/tests/resolvers/Mutation/addEventAttendee.spec.ts index a83a1d0d81..6e371ae0f1 100644 --- a/tests/resolvers/Mutation/addEventAttendee.spec.ts +++ b/tests/resolvers/Mutation/addEventAttendee.spec.ts @@ -10,7 +10,12 @@ import { USER_NOT_FOUND_ERROR, USER_NOT_MEMBER_FOR_ORGANIZATION, } from "../../../src/constants"; -import { AppUserProfile, EventAttendee, User } from "../../../src/models"; +import { + AppUserProfile, + Event, + EventAttendee, + User, +} from "../../../src/models"; import type { MutationAddEventAttendeeArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; import { createTestEvent, type TestEventType } from "../../helpers/events"; @@ -153,39 +158,41 @@ describe("resolvers -> Mutation -> addEventAttendee", () => { }); it(`registers the request user for the event successfully and returns the request user`, async () => { - const eventOrganizationId = testEvent?.organization._id; - const userId = randomTestUser?._id; - - await User.updateOne( - { _id: userId }, - { $addToSet: { joinedOrganizations: eventOrganizationId } }, - ); - - const args: MutationAddEventAttendeeArgs = { - data: { - userId: userId, - eventId: testEvent?._id ?? "", - }, - }; + if (testEvent?.organization) { + const eventOrganizationId = testEvent?.organization._id; + const userId = randomTestUser?._id; - const context = { userId: testUser?._id }; + await User.updateOne( + { _id: userId }, + { $addToSet: { joinedOrganizations: eventOrganizationId } }, + ); - const { addEventAttendee: addEventAttendeeResolver } = await import( - "../../../src/resolvers/Mutation/addEventAttendee" - ); - const payload = await addEventAttendeeResolver?.({}, args, context); + const args: MutationAddEventAttendeeArgs = { + data: { + userId: userId, + eventId: testEvent?._id.toString() ?? "", + }, + }; - const requestUser = await User.findOne({ - _id: userId?._id, - }).lean(); + const context = { userId: testUser?._id }; - const isUserRegistered = await EventAttendee.exists({ - ...args.data, - }); - expect(payload).toEqual(requestUser); - expect(isUserRegistered).toBeTruthy(); + const { addEventAttendee: addEventAttendeeResolver } = await import( + "../../../src/resolvers/Mutation/addEventAttendee" + ); + const payload = await addEventAttendeeResolver?.({}, args, context); + + expect(payload).toBeDefined(); + + const requestUser = await User.findOne({ + _id: userId?._id, + }).lean(); + expect(payload).toEqual(expect.objectContaining(requestUser)); + const isUserRegistered = await EventAttendee.exists({ + ...args.data, + }); + expect(isUserRegistered).toBeTruthy(); + } }); - it(`throws UnauthorizedError if the requestUser is not a member of the organization`, async () => { const { requestContext } = await import("../../../src/libraries"); @@ -199,11 +206,10 @@ describe("resolvers -> Mutation -> addEventAttendee", () => { ); try { - // Create a test user who is not a member of the organization const args: MutationAddEventAttendeeArgs = { data: { userId: testUser?._id, - eventId: testEvent!._id, + eventId: testEvent!._id.toString(), }, }; @@ -291,4 +297,93 @@ describe("resolvers -> Mutation -> addEventAttendee", () => { ); } }); + it("throws NotFoundError if the user is not found after update", async () => { + const { requestContext } = await import("../../../src/libraries"); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + const mockFindByIdAndUpdate = vi + .spyOn(User, "findByIdAndUpdate") + .mockResolvedValueOnce(null); + + const args: MutationAddEventAttendeeArgs = { + data: { + userId: testUser?._id, + eventId: testEvent?._id.toString() ?? "", + }, + }; + + const context = { userId: testUser?._id }; + + try { + const { addEventAttendee: addEventAttendeeResolver } = await import( + "../../../src/resolvers/Mutation/addEventAttendee" + ); + + await addEventAttendeeResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + ); + expect(spy).toHaveBeenLastCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); + } + mockFindByIdAndUpdate.mockRestore(); + }); + it("throws UnauthorizedError when user update fails", async () => { + const { requestContext } = await import("../../../src/libraries"); + + await AppUserProfile.create({ + userId: testUser?._id, + adminFor: [testEvent?.organization._id], + }); + + await Event.findByIdAndUpdate( + testEvent?._id, + { $pull: { admins: testUser?._id } }, + { new: true }, + ); + + await User.findByIdAndUpdate(testUser?._id, { + $push: { joinedOrganizations: testEvent?.organization._id }, + }); + + await EventAttendee.deleteOne({ + userId: testUser?._id, + eventId: testEvent?._id, + }); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + const mockFindByIdAndUpdate = vi + .spyOn(User, "findByIdAndUpdate") + .mockResolvedValueOnce(null); + + const args: MutationAddEventAttendeeArgs = { + data: { + userId: testUser?._id, + eventId: testEvent?._id.toString(), + }, + }; + + const context = { userId: testUser?._id }; + + try { + const { addEventAttendee: addEventAttendeeResolver } = await import( + "../../../src/resolvers/Mutation/addEventAttendee" + ); + + await addEventAttendeeResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + ); + expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); + } + + mockFindByIdAndUpdate.mockRestore(); + }); }); diff --git a/tests/resolvers/Mutation/addPeopleToUserTag.spec.ts b/tests/resolvers/Mutation/addPeopleToUserTag.spec.ts new file mode 100644 index 0000000000..a8f07277c7 --- /dev/null +++ b/tests/resolvers/Mutation/addPeopleToUserTag.spec.ts @@ -0,0 +1,395 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import type { MutationAddPeopleToUserTagArgs } from "../../../src/types/generatedGraphQLTypes"; +import { connect, disconnect } from "../../helpers/db"; + +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; +import { + TAG_NOT_FOUND, + USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../src/constants"; +import { AppUserProfile, TagUser, User } from "../../../src/models"; +import type { TestUserTagType } from "../../helpers/tags"; +import { + createRootTagWithOrg, + createTwoLevelTagsWithOrg, +} from "../../helpers/tags"; +import type { + TestOrganizationType, + TestUserType, +} from "../../helpers/userAndOrg"; +import { createTestUser } from "../../helpers/userAndOrg"; + +let MONGOOSE_INSTANCE: typeof mongoose; + +let adminUser: TestUserType; +let adminUser2: TestUserType; +let testTag2: TestUserTagType; +let testTag: TestUserTagType; +let testSubTag1: TestUserTagType; +let testOrg2: TestOrganizationType; +let randomUser: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [adminUser, , [testTag, testSubTag1]] = await createTwoLevelTagsWithOrg(); + [adminUser2, testOrg2, testTag2] = await createRootTagWithOrg(); + randomUser = await createTestUser(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Mutation -> addPeopleToUserTag", () => { + afterEach(() => { + vi.doUnmock("../../../src/constants"); + vi.resetModules(); + vi.resetAllMocks(); + }); + + it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { + const { requestContext } = await import("../../../src/libraries"); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser?._id], + tagId: testTag?._id.toString() ?? "", + }, + }; + + const context = { userId: new Types.ObjectId().toString() }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + await addPeopleToUserTagResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + ); + expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it(`throws NotFoundError if no tag exists with _id === args.input.tagId `, async () => { + const { requestContext } = await import("../../../src/libraries"); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser?._id], + tagId: new Types.ObjectId().toString(), + }, + }; + + const context = { + userId: adminUser?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + await addPeopleToUserTagResolver?.({}, args, context); + } catch (error: unknown) { + expect(spy).toHaveBeenLastCalledWith(TAG_NOT_FOUND.MESSAGE); + expect((error as Error).message).toEqual( + `Translated ${TAG_NOT_FOUND.MESSAGE}`, + ); + } + }); + + it(`throws Not Authorized Error if the current user is not a superadmin or admin of the organization of the tag being assigned`, async () => { + const { requestContext } = await import("../../../src/libraries"); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser?._id], + tagId: testTag?._id.toString() ?? "", + }, + }; + + const context = { + userId: randomUser?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + await addPeopleToUserTagResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + ); + expect(spy).toHaveBeenLastCalledWith( + `${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + ); + } + }); + + it(`throws NotFoundError if one of the requested users doesn't exist`, async () => { + const { requestContext } = await import("../../../src/libraries"); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser?._id, new Types.ObjectId()], + tagId: testTag?._id.toString() ?? "", + }, + }; + + const context = { userId: adminUser?._id }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + await addPeopleToUserTagResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + ); + expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it(`throws Error if one of the requested users is not a member of organization of the tag being assigned`, async () => { + const { requestContext } = await import("../../../src/libraries"); + + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser?._id.toString(), randomUser?._id.toString()], + tagId: testTag?._id.toString() ?? "", + }, + }; + + const context = { + userId: adminUser?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + await addPeopleToUserTagResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION.MESSAGE}`, + ); + expect(spy).toHaveBeenLastCalledWith( + `${USER_DOES_NOT_BELONG_TO_TAGS_ORGANIZATION.MESSAGE}`, + ); + } + }); + + it(`Tag assignment should be successful and the tag is returned`, async () => { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser2?._id.toString()], + tagId: testTag2?._id.toString() ?? "", + }, + }; + + const context = { + userId: adminUser2?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + const payload = await addPeopleToUserTagResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(testTag2?._id.toString()); + + const tagAssigned = await TagUser.exists({ + tagId: args.input.tagId, + userId: adminUser2?._id, + }); + + expect(tagAssigned).toBeTruthy(); + }); + + it(`Tag assignment should be successful and only new assignments are made and the tag is returned`, async () => { + await User.findOneAndUpdate( + { + _id: randomUser?._id, + }, + { + joinedOrganizations: testOrg2?._id, + }, + ); + + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser2?._id.toString(), randomUser?._id.toString()], + tagId: testTag2?._id.toString() ?? "", + }, + }; + + const context = { + userId: adminUser2?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + const payload = await addPeopleToUserTagResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(testTag2?._id.toString()); + + const tagAssigned = await TagUser.exists({ + tagId: args.input.tagId, + userId: adminUser2?._id, + }); + + expect(tagAssigned).toBeTruthy(); + }); + + it(`Returns the tag if there aren't any new assignments to be made and the tag is returned`, async () => { + await User.findOneAndUpdate( + { + _id: randomUser?._id, + }, + { + joinedOrganizations: testOrg2?._id, + }, + ); + + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser2?._id.toString(), randomUser?._id.toString()], + tagId: testTag2?._id.toString() ?? "", + }, + }; + + const context = { + userId: adminUser2?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + const payload = await addPeopleToUserTagResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(testTag2?._id.toString()); + + const tagAssigned = await TagUser.exists({ + tagId: args.input.tagId, + userId: adminUser2?._id, + }); + + expect(tagAssigned).toBeTruthy(); + }); + + it(`Should assign all the ancestor tags and returns the current tag`, async () => { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [adminUser?._id.toString()], + tagId: testSubTag1?._id.toString() ?? "", + }, + }; + const context = { + userId: adminUser?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + const payload = await addPeopleToUserTagResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(testSubTag1?._id.toString()); + + const subTagAssigned = await TagUser.exists({ + tagId: args.input.tagId, + userId: adminUser?._id, + }); + + const ancestorTagAssigned = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: adminUser?._id, + }); + + expect(subTagAssigned).toBeTruthy(); + expect(ancestorTagAssigned).toBeTruthy(); + }); + + it("throws error if user does not have appUserProfile", async () => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const args: MutationAddPeopleToUserTagArgs = { + input: { + userIds: [randomUser?._id], + tagId: testTag?._id.toString() ?? "", + }, + }; + + const temp = await createTestUser(); + + await AppUserProfile.deleteOne({ + userId: temp?._id, + }); + + const context = { + userId: temp?._id, + }; + + const { addPeopleToUserTag: addPeopleToUserTagResolver } = await import( + "../../../src/resolvers/Mutation/addPeopleToUserTag" + ); + + await addPeopleToUserTagResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + ); + expect(spy).toHaveBeenLastCalledWith( + `${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + ); + } + }); +}); diff --git a/tests/resolvers/Mutation/addUserToGroupChat.spec.ts b/tests/resolvers/Mutation/addUserToGroupChat.spec.ts deleted file mode 100644 index 8f61953651..0000000000 --- a/tests/resolvers/Mutation/addUserToGroupChat.spec.ts +++ /dev/null @@ -1,274 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChat, Organization } from "../../../src/models"; -import type { MutationAddUserToGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it, - vi, -} from "vitest"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_ALREADY_MEMBER_ERROR, - USER_NOT_AUTHORIZED_ADMIN, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testUser = resultArray[0]; - testOrganization = resultArray[1]; - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> addUserToGroupChat", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationAddUserToGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError if no organization exists with _id === groupChat.organization - for groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: new Types.ObjectId().toString(), - }, - }, - ); - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); - - it(`throws UnauthorizedError if current user with _id === context.userId is - not an admin of organization with _id === groupChat.organization for groupChat - with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - await Organization.updateOne( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - ); - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`, - ); - - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); - } - }); - - it(`throws NotFoundError if no user exists with _id === args.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws ConflictError if user with _id === args.userId is already a member - of groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - await addUserToGroupChat?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_ALREADY_MEMBER_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_ALREADY_MEMBER_ERROR.MESSAGE, - ); - } - }); - - it(`add the groupChat with _id === args.chatId and returns it`, async () => { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - users: [], - }, - }, - ); - - const args: MutationAddUserToGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - const { addUserToGroupChat } = await import( - "../../../src/resolvers/Mutation/addUserToGroupChat" - ); - const addUserToGroupChatPayload = await addUserToGroupChat?.( - {}, - args, - context, - ); - expect(addUserToGroupChatPayload?._id).toEqual(testGroupChat?._id); - expect(addUserToGroupChatPayload?.users).toEqual([testUser?._id]); - }); -}); diff --git a/tests/resolvers/Mutation/adminRemoveGroup.spec.ts b/tests/resolvers/Mutation/adminRemoveGroup.spec.ts deleted file mode 100644 index 584bfd7b49..0000000000 --- a/tests/resolvers/Mutation/adminRemoveGroup.spec.ts +++ /dev/null @@ -1,227 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { GroupChat, Organization, User } from "../../../src/models"; -import type { MutationAdminRemoveGroupArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { nanoid } from "nanoid"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ADMIN, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { adminRemoveGroup as adminRemoveGroupResolver } from "../../../src/resolvers/Mutation/adminRemoveGroup"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultsArray = await createTestGroupChat(); - - testUser = resultsArray[0]; - testOrganization = resultsArray[1]; - testGroupChat = resultsArray[2]; - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementation( - (message) => message, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> adminRemoveGroup", () => { - it("throws an error if the user does not have appUserProfile", async () => { - try { - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: `pass${nanoid().toLowerCase()}`, - firstName: `firstName${nanoid().toLowerCase()}`, - lastName: `lastName${nanoid().toLowerCase()}`, - image: null, - }); - - const context = { - userId: newUser?.id, - }; - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - // console.log(error);? - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - it(`throws NotFoundError if no groupChat exists with _id === args.groupId`, async () => { - try { - const args: MutationAdminRemoveGroupArgs = { - groupId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError if no organization exists with _id === group.organization for - group with _id === args.groupId`, async () => { - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: new Types.ObjectId().toString(), - }, - }, - ); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); - - it(`throws NotFoundError if no user exists with _id === context.userId`, async () => { - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws UnauthorizedError if for user with _id === context.userId is not an - admin of orgnanization with _id === args.organizationId`, async () => { - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - { - new: true, - }, - ); - if (updatedOrganization) cacheOrganizations([updatedOrganization]); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - await adminRemoveGroupResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ADMIN.MESSAGE, - ); - } - }); - - it(`deletes the post and returns it`, async () => { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - if (updatedOrganization) cacheOrganizations([updatedOrganization]); - - const args: MutationAdminRemoveGroupArgs = { - groupId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const adminRemoveGroupPayload = await adminRemoveGroupResolver?.( - {}, - args, - context, - ); - - expect(adminRemoveGroupPayload).toEqual({ - ...testGroupChat?.toObject(), - updatedAt: expect.anything(), - }); - }); -}); diff --git a/tests/resolvers/Mutation/assignToUserTags.spec.ts b/tests/resolvers/Mutation/assignToUserTags.spec.ts new file mode 100644 index 0000000000..4d9397d9fb --- /dev/null +++ b/tests/resolvers/Mutation/assignToUserTags.spec.ts @@ -0,0 +1,322 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import type { MutationAssignToUserTagsArgs } from "../../../src/types/generatedGraphQLTypes"; +import { connect, disconnect } from "../../helpers/db"; + +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; +import { + TAG_NOT_FOUND, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../src/constants"; +import { + AppUserProfile, + OrganizationTagUser, + TagUser, + User, +} from "../../../src/models"; +import type { TestUserTagType } from "../../helpers/tags"; +import { + createRootTagsWithOrg, + createTwoLevelTagsWithOrg, +} from "../../helpers/tags"; +import type { + TestOrganizationType, + TestUserType, +} from "../../helpers/userAndOrg"; +import { createTestUser } from "../../helpers/userAndOrg"; + +let MONGOOSE_INSTANCE: typeof mongoose; + +let adminUser: TestUserType; +let adminUser2: TestUserType; +let testTag2: TestUserTagType; +let testTag3: TestUserTagType; +let testTag: TestUserTagType; +let testSubTag1: TestUserTagType; +let testOrg1: TestOrganizationType; +let testOrg2: TestOrganizationType; +let randomUser1: TestUserType; +let randomUser2: TestUserType; +let randomUser3: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [adminUser, testOrg1, [testTag, testSubTag1]] = + await createTwoLevelTagsWithOrg(); + [adminUser2, testOrg2, [testTag2, testTag3]] = await createRootTagsWithOrg(2); + randomUser1 = await createTestUser(); + randomUser2 = await createTestUser(); + randomUser3 = await createTestUser(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Mutation -> assignToUserTags", () => { + afterEach(() => { + vi.doUnmock("../../../src/constants"); + vi.resetModules(); + vi.resetAllMocks(); + }); + + it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: new Types.ObjectId().toString() }, + expectedError: USER_NOT_FOUND_ERROR.MESSAGE, + }); + }); + + it(`throws NotFoundError if no tag exists with _id === args.input.currentTagId `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: new Types.ObjectId().toString(), + }, + }, + context: { userId: adminUser?._id }, + expectedError: TAG_NOT_FOUND.MESSAGE, + }); + }); + + it(`throws Not Authorized Error if the current user is not a superadmin or admin of the organization `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: randomUser1?._id }, + expectedError: USER_NOT_AUTHORIZED_ERROR.MESSAGE, + }); + }); + + it(`throws NotFoundError if one of the selected tags doesn't exist`, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [ + testTag?._id.toString() ?? "", + new Types.ObjectId().toString(), + ], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: adminUser?._id }, + expectedError: TAG_NOT_FOUND.MESSAGE, + }); + }); + + it("throws error if user does not have appUserProfile", async () => { + const temp = await createTestUser(); + await AppUserProfile.deleteOne({ + userId: temp?._id, + }); + + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: temp?._id }, + expectedError: USER_NOT_AUTHORIZED_ERROR.MESSAGE, + }); + }); + + it(`Tag assignment should be successful and the tag is returned`, async () => { + // assign testTag2 to random users + await Promise.all([ + User.findOneAndUpdate( + { + _id: randomUser2?._id, + }, + { + joinedOrganizations: testOrg2, + }, + ), + User.findOneAndUpdate( + { + _id: randomUser3?._id, + }, + { + joinedOrganizations: testOrg2, + }, + ), + TagUser.create({ + userId: randomUser2?._id, + tagId: testTag2?._id, + organizationId: testTag2?.organizationId, + }), + TagUser.create({ + userId: randomUser3?._id, + tagId: testTag2?._id, + organizationId: testTag2?.organizationId, + }), + ]); + + // now assign them to a new tag with the help of the mutation + const args: MutationAssignToUserTagsArgs = { + input: { + selectedTagIds: [testTag3?._id.toString() ?? ""], + currentTagId: testTag2?._id.toString() ?? "", + }, + }; + + const context = { + userId: adminUser2?._id, + }; + + const { assignToUserTags: assignToUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/assignToUserTags" + ); + + const payload = await assignToUserTagsResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(testTag2?._id.toString()); + + const tagAssignedToRandomUser2 = await TagUser.exists({ + tagId: testTag3, + userId: randomUser2?._id, + }); + + const tagAssignedToRandomUser3 = await TagUser.exists({ + tagId: testTag3, + userId: randomUser3?._id, + }); + + expect(tagAssignedToRandomUser2).toBeTruthy(); + expect(tagAssignedToRandomUser3).toBeTruthy(); + }); + + it(`Should assign all the ancestor tags and returns the current tag`, async () => { + // create a new tag with the organization + const newTestTag = await OrganizationTagUser.create({ + name: "newTestTag", + organizationId: testOrg1?._id, + }); + + // assign this new test tag to random users + await Promise.all([ + User.findOneAndUpdate( + { + _id: randomUser2?._id, + }, + { + joinedOrganizations: testOrg1, + }, + ), + User.findOneAndUpdate( + { + _id: randomUser3?._id, + }, + { + joinedOrganizations: testOrg1, + }, + ), + TagUser.create({ + userId: randomUser2?._id, + tagId: newTestTag?._id, + organizationId: newTestTag?.organizationId, + }), + TagUser.create({ + userId: randomUser3?._id, + tagId: newTestTag?._id, + organizationId: newTestTag?.organizationId, + }), + ]); + + // now assign them a new sub tag, which will automatically assign them the parent tag also + const args: MutationAssignToUserTagsArgs = { + input: { + selectedTagIds: [testSubTag1?._id.toString() ?? ""], + currentTagId: newTestTag?._id.toString() ?? "", + }, + }; + const context = { + userId: adminUser?._id, + }; + + const { assignToUserTags: assignToUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/assignToUserTags" + ); + + const payload = await assignToUserTagsResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(newTestTag?._id.toString()); + + const subTagAssignedToRandomUser2 = await TagUser.exists({ + tagId: testSubTag1?._id, + userId: randomUser2?._id, + }); + + const subTagAssignedToRandomUser3 = await TagUser.exists({ + tagId: testSubTag1?._id, + userId: randomUser3?._id, + }); + + expect(subTagAssignedToRandomUser2).toBeTruthy(); + expect(subTagAssignedToRandomUser3).toBeTruthy(); + + const ancestorTagAssignedToRandomUser2 = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: randomUser2?._id, + }); + + const ancestorTagAssignedToRandomUser3 = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: randomUser3?._id, + }); + + expect(ancestorTagAssignedToRandomUser2).toBeTruthy(); + expect(ancestorTagAssignedToRandomUser3).toBeTruthy(); + }); +}); + +const testErrorScenario = async ({ + args, + context, + expectedError, +}: { + args: MutationAssignToUserTagsArgs; + context: { userId: string }; + expectedError: string; +}): Promise => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + try { + const { assignToUserTags: assignToUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/assignToUserTags" + ); + await assignToUserTagsResolver?.({}, args, context); + throw new Error("Expected error was not thrown"); + } catch (error: unknown) { + if (error instanceof Error) { + expect(error.message).toEqual(`Translated ${expectedError}`); + } else { + throw new Error("Unexpected error type"); + } + expect(spy).toHaveBeenLastCalledWith(expectedError); + } +}; diff --git a/tests/resolvers/Mutation/createActionItem.spec.ts b/tests/resolvers/Mutation/createActionItem.spec.ts index e1093a4975..c8b35b5285 100644 --- a/tests/resolvers/Mutation/createActionItem.spec.ts +++ b/tests/resolvers/Mutation/createActionItem.spec.ts @@ -1,85 +1,57 @@ -import "dotenv/config"; import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; +import { connect, disconnect } from "../../helpers/db"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { + TestEventType, + TestEventVolunteerGroupType, + TestEventVolunteerType, +} from "../../helpers/events"; +import type { TestUserType } from "../../helpers/user"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceActionItem } from "../../../src/models"; +import { ActionItemCategory } from "../../../src/models"; import { ACTION_ITEM_CATEGORY_IS_DISABLED, ACTION_ITEM_CATEGORY_NOT_FOUND_ERROR, EVENT_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, - USER_NOT_MEMBER_FOR_ORGANIZATION, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_NOT_FOUND_ERROR, } from "../../../src/constants"; -import { createActionItem as createActionItemResolver } from "../../../src/resolvers/Mutation/createActionItem"; -import type { MutationCreateActionItemArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import { createTestUser } from "../../helpers/userAndOrg"; - -import { nanoid } from "nanoid"; -import { - ActionItemCategory, - AppUserProfile, - Event, - User, -} from "../../../src/models"; -import type { TestActionItemCategoryType } from "../../helpers/actionItemCategory"; -import { createTestCategory } from "../../helpers/actionItemCategory"; -import type { TestEventType } from "../../helpers/events"; +import { requestContext } from "../../../src/libraries"; +import { createActionItem } from "../../../src/resolvers/Mutation/createActionItem"; +import type { TestOrganizationType } from "../../helpers/userAndOrg"; +import type { TestActionItemType } from "../../helpers/actionItem"; -let randomUser: TestUserType; -let randomUser2: TestUserType; -// let superAdminTestUserAppProfile: TestAppUserProfileType; -let testUser: TestUserType; +let MONGOOSE_INSTANCE: typeof mongoose; let testOrganization: TestOrganizationType; -let testCategory: TestActionItemCategoryType; -let testDisabledCategory: TestActionItemCategoryType; let testEvent: TestEventType; -let MONGOOSE_INSTANCE: typeof mongoose; +let testUser1: TestUserType; +let testActionItem1: TestActionItemType; +let testEventVolunteer1: TestEventVolunteerType; +let testEventVolunteerGroup: TestEventVolunteerGroupType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const { requestContext } = await import("../../../src/libraries"); vi.spyOn(requestContext, "translate").mockImplementation( (message) => message, ); - - randomUser = await createTestUser(); - randomUser2 = await createTestUser(); - - await AppUserProfile.updateOne( - { - userId: randomUser2?._id, - }, - { - isSuperAdmin: true, - }, - ); - - [testUser, testOrganization, testCategory] = await createTestCategory(); - - testDisabledCategory = await ActionItemCategory.create({ - name: "a disabled category", - organizationId: testOrganization?._id, - isDisabled: true, - creatorId: testUser?._id, - }); - - testEvent = await Event.create({ - title: `title${nanoid().toLowerCase()}`, - description: `description${nanoid().toLowerCase()}`, - allDay: true, - startDate: new Date(), - recurring: false, - isPublic: true, - isRegisterable: true, - creatorId: randomUser?._id, - admins: [randomUser?._id], - organization: testOrganization?._id, - }); + const [ + organization, + event, + user1, + , + volunteer1, + , + volunteerGroup, + actionItem1, + ] = await createVolunteerAndActions(); + + testOrganization = organization; + testEvent = event; + testUser1 = user1; + testEventVolunteer1 = volunteer1; + testEventVolunteerGroup = volunteerGroup; + testActionItem1 = actionItem1; }); afterAll(async () => { @@ -87,255 +59,161 @@ afterAll(async () => { }); describe("resolvers -> Mutation -> createActionItem", () => { - it(`throws NotFoundError if no user exists with _id === context.userId`, async () => { - try { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, - }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - await createActionItemResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError if no actionItemCategory exists with _id === args.actionItemCategoryId`, async () => { + it(`throws EventVolunteer Not Found`, async () => { try { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, + (await createActionItem?.( + {}, + { + data: { + assigneeId: testEvent?._id, + assigneeType: "EventVolunteer", + }, + actionItemCategoryId: testEventVolunteer1?._id, }, - actionItemCategoryId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?._id, - }; - - await createActionItemResolver?.({}, args, context); + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; } catch (error: unknown) { expect((error as Error).message).toEqual( - ACTION_ITEM_CATEGORY_NOT_FOUND_ERROR.MESSAGE, + EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE, ); } }); - it(`throws ConflictError if the actionItemCategory is disabled`, async () => { + it(`throws EventVolunteerGroup Not Found`, async () => { try { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, + (await createActionItem?.( + {}, + { + data: { + assigneeId: testEvent?._id, + assigneeType: "EventVolunteerGroup", + }, + actionItemCategoryId: testEventVolunteer1?._id, }, - actionItemCategoryId: testDisabledCategory._id, - }; - - const context = { - userId: testUser?._id, - }; - - await createActionItemResolver?.({}, args, context); + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; } catch (error: unknown) { expect((error as Error).message).toEqual( - ACTION_ITEM_CATEGORY_IS_DISABLED.MESSAGE, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, ); } }); - it(`throws NotFoundError if no user exists with _id === args.data.assigneeId`, async () => { + it(`throws ActionItemCategory Not Found`, async () => { try { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: new Types.ObjectId().toString(), + (await createActionItem?.( + {}, + { + data: { + assigneeId: testEventVolunteer1?._id, + assigneeType: "EventVolunteer", + }, + actionItemCategoryId: testEventVolunteer1?._id, }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: testUser?._id, - }; - - await createActionItemResolver?.({}, args, context); + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual( + ACTION_ITEM_CATEGORY_NOT_FOUND_ERROR.MESSAGE, + ); } }); - it(`throws NotFoundError new assignee is not a member of the organization`, async () => { + it(`throws ActionItemCategory is Disabled`, async () => { + const disabledCategory = await ActionItemCategory.create({ + creatorId: testUser1?._id, + organizationId: testOrganization?._id, + name: "Disabled Category", + isDisabled: true, + }); try { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, + (await createActionItem?.( + {}, + { + data: { + assigneeId: testEventVolunteer1?._id, + assigneeType: "EventVolunteer", + }, + actionItemCategoryId: disabledCategory?._id.toString(), }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: testUser?._id, - }; - - await createActionItemResolver?.({}, args, context); + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; } catch (error: unknown) { expect((error as Error).message).toEqual( - USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE, + ACTION_ITEM_CATEGORY_IS_DISABLED.MESSAGE, ); } }); - it(`throws NotFoundError if no event exists with _id === args.data.eventId`, async () => { - await User.findOneAndUpdate( - { - _id: randomUser?._id, - }, - { - $push: { joinedOrganizations: testOrganization?._id }, - }, - ); - + it(`throws Event Not Found`, async () => { try { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, - eventId: new Types.ObjectId().toString(), + (await createActionItem?.( + {}, + { + data: { + assigneeId: testEventVolunteer1?._id, + assigneeType: "EventVolunteer", + eventId: testUser1?._id.toString(), + }, + actionItemCategoryId: testActionItem1.actionItemCategory.toString(), }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: randomUser?._id, - }; - - await createActionItemResolver?.({}, args, context); + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; } catch (error: unknown) { expect((error as Error).message).toEqual(EVENT_NOT_FOUND_ERROR.MESSAGE); } }); - it(`throws NotAuthorizedError if the user is not authorized for performing the operation`, async () => { - try { - const args: MutationCreateActionItemArgs = { + it(`Create Action Item (EventVolunteer) `, async () => { + const createdItem = (await createActionItem?.( + {}, + { data: { - assigneeId: randomUser?._id, + assigneeId: testEventVolunteer1?._id, + assigneeType: "EventVolunteer", + eventId: testEvent?._id.toString(), }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: randomUser?._id, - }; - - await createActionItemResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`creates the actionItem when user is authorized as an eventAdmin`, async () => { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, - eventId: testEvent?._id.toString() ?? "", + actionItemCategoryId: testActionItem1.actionItemCategory.toString(), }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: randomUser?._id, - }; - - const createActionItemPayload = await createActionItemResolver?.( - {}, - args, - context, - ); + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; - expect(createActionItemPayload).toEqual( - expect.objectContaining({ - actionItemCategory: testCategory?._id, - }), - ); + expect(createdItem).toBeDefined(); + expect(createdItem.creator).toEqual(testUser1?._id); }); - it(`creates the actionItem when user is authorized as an orgAdmin`, async () => { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, - }, - actionItemCategoryId: testCategory?._id, - }; - - const context = { - userId: testUser?._id, - }; - - const createActionItemPayload = await createActionItemResolver?.( + it(`Create Action Item (EventVolunteerGroup) `, async () => { + const createdItem = (await createActionItem?.( {}, - args, - context, - ); - - expect(createActionItemPayload).toEqual( - expect.objectContaining({ - actionItemCategory: testCategory?._id, - }), - ); - }); - - it(`creates the actionItem when user is authorized as superadmin`, async () => { - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, + { + data: { + assigneeId: testEventVolunteerGroup?._id, + assigneeType: "EventVolunteerGroup", + eventId: testEvent?._id.toString(), + }, + actionItemCategoryId: testActionItem1.actionItemCategory.toString(), }, - actionItemCategoryId: testCategory?._id, - }; + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; - const context = { - userId: randomUser2?._id, - }; - // const superAdmin = await AppUserProfile.findOne({ - // userId: randomUser2?._id, - // }); - // console.log(superAdmin) + expect(createdItem).toBeDefined(); + expect(createdItem.creator).toEqual(testUser1?._id); + }); - const createActionItemPayload = await createActionItemResolver?.( + it(`Create Action Item (User) `, async () => { + const createdItem = (await createActionItem?.( {}, - args, - context, - ); - - expect(createActionItemPayload).toEqual( - expect.objectContaining({ - actionItemCategory: testCategory?._id, - }), - ); - }); - it("throws error if the user does not have appUserProfile", async () => { - await AppUserProfile.deleteOne({ - userId: randomUser?._id, - }); - const args: MutationCreateActionItemArgs = { - data: { - assigneeId: randomUser?._id, + { + data: { + assigneeId: testUser1?._id.toString() as string, + assigneeType: "User", + }, + actionItemCategoryId: testActionItem1.actionItemCategory.toString(), }, - actionItemCategoryId: testCategory?._id, - }; - const context = { - userId: randomUser?._id, - }; - try { - await createActionItemResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceActionItem; + + expect(createdItem).toBeDefined(); + expect(createdItem.creator).toEqual(testUser1?._id); }); }); diff --git a/tests/resolvers/Mutation/createDirectChat.spec.ts b/tests/resolvers/Mutation/createChat.spec.ts similarity index 61% rename from tests/resolvers/Mutation/createDirectChat.spec.ts rename to tests/resolvers/Mutation/createChat.spec.ts index 7c46e94092..560c9b6207 100644 --- a/tests/resolvers/Mutation/createDirectChat.spec.ts +++ b/tests/resolvers/Mutation/createChat.spec.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import type mongoose from "mongoose"; import { Types } from "mongoose"; -import type { MutationCreateDirectChatArgs } from "../../../src/types/generatedGraphQLTypes"; +import type { MutationCreateChatArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; import { @@ -29,7 +29,6 @@ let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); const resultsArray = await createTestUserAndOrganization(); - testUser = resultsArray[0]; testOrganization = resultsArray[1]; }); @@ -38,7 +37,7 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Mutation -> createDirectChat", () => { +describe("resolvers -> Mutation -> createChat", () => { afterEach(() => { vi.doUnmock("../../../src/constants"); vi.resetModules(); @@ -50,20 +49,21 @@ describe("resolvers -> Mutation -> createDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationCreateDirectChatArgs = { + const args: MutationCreateChatArgs = { data: { organizationId: new Types.ObjectId().toString(), userIds: [], + isGroup: true, }, }; const context = { userId: testUser?.id, }; - const { createDirectChat: createDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/createDirectChat" + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" ); - await createDirectChatResolver?.({}, args, context); + await createChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual( @@ -78,10 +78,11 @@ describe("resolvers -> Mutation -> createDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationCreateDirectChatArgs = { + const args: MutationCreateChatArgs = { data: { - organizationId: testOrganization?.id, + organizationId: testOrganization?._id, userIds: [new Types.ObjectId().toString()], + isGroup: true, }, }; @@ -89,37 +90,60 @@ describe("resolvers -> Mutation -> createDirectChat", () => { userId: testUser?.id, }; - const { createDirectChat: createDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/createDirectChat" + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" ); - await createDirectChatResolver?.({}, args, context); + await createChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } }); - it(`creates the directChat and returns it`, async () => { - const args: MutationCreateDirectChatArgs = { + it(`creates the chat and returns it`, async () => { + const args: MutationCreateChatArgs = { data: { organizationId: testOrganization?.id, userIds: [testUser?.id], + isGroup: false, }, }; const context = { userId: testUser?.id, }; - const { createDirectChat: createDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/createDirectChat" + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" ); - const createDirectChatPayload = await createDirectChatResolver?.( - {}, - args, - context, + const createChatPayload = await createChatResolver?.({}, args, context); + + expect(createChatPayload).toEqual( + expect.objectContaining({ + creatorId: testUser?._id, + users: [testUser?._id], + }), ); + }); + + it(`creates the chat and returns it`, async () => { + const args: MutationCreateChatArgs = { + data: { + organizationId: testOrganization?.id, + userIds: [testUser?.id], + isGroup: false, + }, + }; + + const context = { + userId: testUser?.id, + }; + const { createChat: createChatResolver } = await import( + "../../../src/resolvers/Mutation/createChat" + ); + + const createChatPayload = await createChatResolver?.({}, args, context); - expect(createDirectChatPayload).toEqual( + expect(createChatPayload).toEqual( expect.objectContaining({ creatorId: testUser?._id, users: [testUser?._id], diff --git a/tests/resolvers/Mutation/createEventVolunteer.spec.ts b/tests/resolvers/Mutation/createEventVolunteer.spec.ts index 8d339b4370..7734361eef 100644 --- a/tests/resolvers/Mutation/createEventVolunteer.spec.ts +++ b/tests/resolvers/Mutation/createEventVolunteer.spec.ts @@ -45,10 +45,11 @@ beforeAll(async () => { [eventAdminUser, , testEvent] = await createTestEvent(); testGroup = await EventVolunteerGroup.create({ - creatorId: eventAdminUser?._id, - eventId: testEvent?._id, - leaderId: eventAdminUser?._id, + creator: eventAdminUser?._id, + event: testEvent?._id, + leader: eventAdminUser?._id, name: "Test group", + volunteers: [eventAdminUser?._id, testUser2?._id, testUser1?._id], }); }); @@ -230,22 +231,15 @@ describe("resolvers -> Mutation -> createEventVolunteer", () => { context, ); - const updatedGroup = await EventVolunteerGroup.findOne({ - _id: testGroup?._id, - }); - - expect(updatedGroup?.volunteers.toString()).toEqual( - [createdVolunteer?._id.toString()].toString(), - ); - expect(createdVolunteer).toEqual( expect.objectContaining({ - eventId: new Types.ObjectId(testEvent?.id), - userId: testUser2?._id, - groupId: testGroup?._id, - creatorId: eventAdminUser?._id, - isInvited: true, - isAssigned: false, + event: new Types.ObjectId(testEvent?.id), + user: testUser2?._id, + groups: [], + creator: eventAdminUser?._id, + hasAccepted: false, + isPublic: true, + hoursVolunteered: 0, }), ); }); diff --git a/tests/resolvers/Mutation/createEventVolunteerGroup.spec.ts b/tests/resolvers/Mutation/createEventVolunteerGroup.spec.ts index f41663b29b..5604676eac 100644 --- a/tests/resolvers/Mutation/createEventVolunteerGroup.spec.ts +++ b/tests/resolvers/Mutation/createEventVolunteerGroup.spec.ts @@ -54,6 +54,8 @@ describe("resolvers -> Mutation -> createEventVolunteerGroup", () => { const args: MutationCreateEventVolunteerGroupArgs = { data: { name: "Test group", + leaderId: testUser?._id, + volunteerUserIds: [testUser?._id], eventId: testEvent?._id, }, }; @@ -82,6 +84,8 @@ describe("resolvers -> Mutation -> createEventVolunteerGroup", () => { const args: MutationCreateEventVolunteerGroupArgs = { data: { name: "Test group", + leaderId: testUser?._id, + volunteerUserIds: [testUser?._id], eventId: new Types.ObjectId().toString(), }, }; @@ -111,6 +115,8 @@ describe("resolvers -> Mutation -> createEventVolunteerGroup", () => { const args: MutationCreateEventVolunteerGroupArgs = { data: { name: "Test group", + leaderId: testUser?._id, + volunteerUserIds: [testUser?._id], eventId: testEvent?._id, }, }; @@ -137,6 +143,8 @@ describe("resolvers -> Mutation -> createEventVolunteerGroup", () => { const args: MutationCreateEventVolunteerGroupArgs = { data: { name: "Test group", + leaderId: eventAdminUser?._id, + volunteerUserIds: [testUser?._id], eventId: testEvent?._id, }, }; @@ -163,9 +171,9 @@ describe("resolvers -> Mutation -> createEventVolunteerGroup", () => { expect(createdGroup).toEqual( expect.objectContaining({ name: "Test group", - eventId: new Types.ObjectId(testEvent?.id), - creatorId: eventAdminUser?._id, - leaderId: eventAdminUser?._id, + event: new Types.ObjectId(testEvent?.id), + creator: eventAdminUser?._id, + leader: eventAdminUser?._id, }), ); }); diff --git a/tests/resolvers/Mutation/createGroupChat.spec.ts b/tests/resolvers/Mutation/createGroupChat.spec.ts deleted file mode 100644 index 7fc0400b7a..0000000000 --- a/tests/resolvers/Mutation/createGroupChat.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { MutationCreateGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { createGroupChat as createGroupChatResolver } from "../../../src/resolvers/Mutation/createGroupChat"; -import { - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let MONGOOSE_INSTANCE: typeof mongoose; -let testOrganization: TestOrganizationType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultsArray = await createTestUserAndOrganization(); - - testUser = resultsArray[0]; - testOrganization = resultsArray[1]; - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementation( - (message) => message, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> createGroupChat", () => { - it(`throws NotFoundError if no organization exists with _id === args.data.organizationId`, async () => { - try { - const args: MutationCreateGroupChatArgs = { - data: { - organizationId: new Types.ObjectId().toString(), - title: "", - userIds: [], - }, - }; - - const context = { - userId: testUser?.id, - }; - - await createGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); - - it(`throws NotFoundError if no user exists for any one of the ids in args.data.userIds`, async () => { - try { - const args: MutationCreateGroupChatArgs = { - data: { - organizationId: testOrganization?.id, - title: "", - userIds: [new Types.ObjectId().toString()], - }, - }; - - const context = { - userId: testUser?.id, - }; - - await createGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`creates the groupChat and returns it`, async () => { - const args: MutationCreateGroupChatArgs = { - data: { - organizationId: testOrganization?.id, - title: "title", - userIds: [testUser?.id], - }, - }; - - const context = { - userId: testUser?.id, - }; - - const createGroupChatPayload = await createGroupChatResolver?.( - {}, - args, - context, - ); - - expect(createGroupChatPayload).toEqual( - expect.objectContaining({ - title: "title", - creatorId: testUser?._id, - users: [testUser?._id], - organization: testOrganization?._id, - }), - ); - }); -}); diff --git a/tests/resolvers/Mutation/createMessageChat.spec.ts b/tests/resolvers/Mutation/createMessageChat.spec.ts deleted file mode 100644 index d77a2b1d54..0000000000 --- a/tests/resolvers/Mutation/createMessageChat.spec.ts +++ /dev/null @@ -1,239 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { InterfaceMessageChat } from "../../../src/models"; -import { AppUserProfile, User } from "../../../src/models"; -import type { MutationCreateMessageChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { nanoid } from "nanoid"; -import { - afterAll, - afterEach, - beforeAll, - describe, - expect, - it, - vi, -} from "vitest"; -import { - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let testUsers: TestUserType[]; -// let testAppUserProfile: TestAppUserProfileType[]; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - - testUsers = await User.insertMany([ - { - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: "password", - firstName: "firstName", - lastName: "lastName", - }, - { - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: "password", - firstName: "firstName", - lastName: "lastName", - }, - ]); - const appUserProfiles = testUsers.map((user) => ({ - userId: user?._id, - })); - await AppUserProfile.insertMany(appUserProfiles); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> createMessageChat", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no user exists with _id === args.data.receiver`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: new Types.ObjectId().toString(), - }, - }; - - const context = { - userId: testUsers[0]?.id, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - it(`throws user not found error if no user exist with id==context.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: testUsers[1]?.id, - }, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - // console.log(error); - expect(spy).toHaveBeenCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - it("throws error if receiver user does not have appProfile", async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: `pass${nanoid().toLowerCase()}`, - firstName: `firstName${nanoid().toLowerCase()}`, - lastName: `lastName${nanoid().toLowerCase()}`, - image: null, - }); - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: newUser.id, - }, - }; - - const context = { - userId: testUsers[0]?.id, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, - ); - } - }); - it("throws error if sender user does not have appProfile", async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const newUser = await User.create({ - email: `email${nanoid().toLowerCase()}@gmail.com`, - password: `pass${nanoid().toLowerCase()}`, - firstName: `firstName${nanoid().toLowerCase()}`, - lastName: `lastName${nanoid().toLowerCase()}`, - image: null, - }); - const args: MutationCreateMessageChatArgs = { - data: { - message: "", - receiver: testUsers[1]?.id, - }, - }; - - const context = { - userId: newUser.id, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - await createMessageChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, - ); - } - }); - - it(`creates the organization and returns it`, async () => { - const args: MutationCreateMessageChatArgs = { - data: { - message: "message", - receiver: testUsers[1]?.id, - }, - }; - - const pubsub = { - publish: ( - _action: "CHAT_CHANNEL", - _payload: { - directMessageChat: InterfaceMessageChat; - }, - ): { - _action: string; - _payload: { directMessageChat: InterfaceMessageChat }; - } => { - return { _action, _payload }; - }, - }; - - const context = { - userId: testUsers[0]?.id, - pubsub, - }; - - const { createMessageChat: createMessageChatResolver } = await import( - "../../../src/resolvers/Mutation/createMessageChat" - ); - const createMessageChatPayload = await createMessageChatResolver?.( - {}, - args, - context, - ); - - expect(createMessageChatPayload).toEqual( - expect.objectContaining({ - sender: testUsers[0]?._id, - receiver: testUsers[1]?._id, - message: "message", - languageBarrier: false, - }), - ); - }); -}); diff --git a/tests/resolvers/Mutation/createPost.spec.ts b/tests/resolvers/Mutation/createPost.spec.ts index 6d7e154e6e..8a03f389e6 100644 --- a/tests/resolvers/Mutation/createPost.spec.ts +++ b/tests/resolvers/Mutation/createPost.spec.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import type mongoose from "mongoose"; import { Types } from "mongoose"; -import type { MutationCreatePostArgs } from "../../../src/types/generatedGraphQLTypes"; +import type { Response } from "express"; import { connect, disconnect } from "../../helpers/db"; import { @@ -14,18 +14,17 @@ import { vi, } from "vitest"; import { - BASE_URL, + INTERNAL_SERVER_ERROR, + INVALID_FILE_TYPE, LENGTH_VALIDATION_ERROR, ORGANIZATION_NOT_FOUND_ERROR, + PLEASE_PROVIDE_TITLE, USER_NOT_AUTHORIZED_ERROR, USER_NOT_AUTHORIZED_TO_PIN, USER_NOT_FOUND_ERROR, USER_NOT_MEMBER_FOR_ORGANIZATION, } from "../../../src/constants"; import { AppUserProfile, Organization, Post } from "../../../src/models"; -import { createPost as createPostResolverImage } from "../../../src/resolvers/Mutation/createPost"; -import * as uploadEncodedImage from "../../../src/utilities/encodedImageStorage/uploadEncodedImage"; -import * as uploadEncodedVideo from "../../../src/utilities/encodedVideoStorage/uploadEncodedVideo"; import type { TestOrganizationType, TestUserType, @@ -34,14 +33,31 @@ import { createTestUser, createTestUserAndOrganization, } from "../../helpers/userAndOrg"; +import type { InterfaceAuthenticatedRequest } from "../../../src/middleware"; +import { createPost } from "../../../src/REST/controllers/mutation"; +import * as uploadFileService from "../../../src/REST/services/file"; +import type { InterfaceUploadedFileResponse } from "../../../src/REST/services/file/uploadFile"; + +vi.mock("../../../src/libraries/requestContext", () => ({ + translate: (message: string): string => `Translated ${message}`, +})); let testUser: TestUserType; let testOrganization: TestOrganizationType; let MONGOOSE_INSTANCE: typeof mongoose; -vi.mock("../../utilities/uploadEncodedImage", () => ({ - uploadEncodedImage: vi.fn(), -})); +interface InterfaceMockResponse extends Omit { + status(code: number): InterfaceMockResponse; + json(data: unknown): InterfaceMockResponse; +} + +// Mock response object with proper return type +const mockResponse = (): InterfaceMockResponse => { + const res = {} as InterfaceMockResponse; + res.status = vi.fn().mockReturnValue(res); + res.json = vi.fn().mockReturnValue(res); + return res; +}; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); @@ -54,559 +70,346 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Mutation -> createPost", () => { +describe("controllers -> post -> createPost", () => { afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - vi.resetAllMocks(); + vi.clearAllMocks(); }); - it(`throws NotFoundError if no user exists with _id === context.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: "", - text: "", - videoUrl: "", - title: "", - }, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - await createPostResolver?.({}, args, context); - expect.fail(); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } + it("should throw NotFoundError if no user exists with _id === userId", async () => { + const req = { + userId: new Types.ObjectId().toString(), + body: { + organizationId: testOrganization?._id, + text: "Test post", + }, + } as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await createPost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + }); }); - it(`throws NotFoundError if no organization exists with _id === args.data.organizationId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: new Types.ObjectId().toString(), - text: "", - videoUrl: "", - title: "", - imageUrl: null, - }, - }; - - const context = { - userId: testUser?.id, - }; - - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - await createPostResolver?.({}, args, context); - expect.fail(); - } catch (error) { - if (error instanceof Error) { - expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect(error.message).toEqual( - `Translated ${ORGANIZATION_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - } + it("should throw NotFoundError if no organization exists with _id === organizationId", async () => { + const req = { + userId: testUser?.id, + body: { + organizationId: new Types.ObjectId().toString(), + text: "Test post", + }, + } as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await createPost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${ORGANIZATION_NOT_FOUND_ERROR.MESSAGE}`, + }); }); - it("throws error if AppUserProfile is not found", async () => { + it("should throw UnauthorizedError if AppUserProfile is not found", async () => { const userWithoutProfileId = await createTestUser(); await AppUserProfile.findByIdAndDelete( userWithoutProfileId?.appUserProfileId, ); - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: "", - text: "", - videoUrl: "", - title: "", - }, - }; - - const context = { - userId: userWithoutProfileId?.id, - }; - - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - await createPostResolver?.({}, args, context); - expect.fail(); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, - ); - } - }); - it(`throws USER_NOT_AUTHORIZED_TO_PIN ERROR if the user is not authorized to pin the post`, async () => { - const organizationWithNoAdmin = await createTestUserAndOrganization( - true, - false, - ); - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: organizationWithNoAdmin[1]?._id, - text: "New Post Text", - videoUrl: "http://dummyURL.com/", - title: "New Post Title", - imageUrl: "http://dummyURL.com/image/", - pinned: true, - }, - }; - - const context = { - userId: organizationWithNoAdmin[0]?.id, - }; - - expect(args.data.pinned).toBe(true); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - await createPostResolver?.({}, args, context); - expect.fail(); - } catch (error) { - if (error instanceof Error) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_TO_PIN.MESSAGE); - expect(error.message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_TO_PIN.MESSAGE}`, - ); - } - } + const req = { + userId: userWithoutProfileId?.id, + body: { + organizationId: testOrganization?._id, + text: "Test post", + }, + } as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await createPost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + }); }); - it("throws error if user is not member of the organization and is not superadmin", async () => { - const organizationWithNoMember = await createTestUserAndOrganization(false); - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: organizationWithNoMember[1]?._id, - text: "New Post Text", - videoUrl: "http://dummyURL.com/", - title: "New Post Title", - imageUrl: "http://dummyURL.com/image/", - pinned: true, - }, - }; - - const context = { - userId: organizationWithNoMember[0]?.id, - }; - - expect(args.data.pinned).toBe(true); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - await createPostResolver?.({}, args, context); - expect.fail(); - } catch (error) { - if (error instanceof Error) { - expect(spy).toBeCalledWith(USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE); - expect(error.message).toEqual( - `Translated ${USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE}`, - ); - } - } + it("should throw error if user is not member of the organization and is not superadmin", async () => { + const [nonMemberUser] = await createTestUserAndOrganization(false); + + const req = { + userId: nonMemberUser?.id, + body: { + organizationId: testOrganization?._id, + text: "Test post", + }, + } as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await createPost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE}`, + }); }); - it(`pinned post should be successfully added to the organization`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => `Translated ${message}`, + it("should throw error if trying to pin post without proper authorization", async () => { + const [nonAdminUser, nonAdminOrg] = await createTestUserAndOrganization( + true, + false, ); - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?.id, - text: "New Post Text", - videoUrl: "http://dummyURL.com/", - title: "New Post Title", - imageUrl: "http://dummyURL.com/image/", + const req = { + userId: nonAdminUser?.id, + body: { + organizationId: nonAdminOrg?._id, + text: "Test post", + title: "Test title", pinned: true, }, - }; - const context = { - userId: testUser?.id, - }; + } as InterfaceAuthenticatedRequest; - expect(args.data.pinned).toBe(true); + const res = mockResponse(); + await createPost(req, res); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - const createdPost = await createPostResolver?.({}, args, context); - expect(createdPost).toEqual( - expect.objectContaining({ - text: "New Post Text", - videoUrl: null, // Update the expected value to match the received value - title: "New Post Title", + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_AUTHORIZED_TO_PIN.MESSAGE}`, + }); + }); + + it("should throw error if pinned post has no title", async () => { + const req = { + userId: testUser?.id, + body: { + organizationId: testOrganization?._id, + text: "Test post", pinned: true, - }), - ); + }, + } as InterfaceAuthenticatedRequest; - const updatedTestOrg = await Organization.findOne({ - _id: testOrganization?.id, - }).lean(); + const res = mockResponse(); + await createPost(req, res); - expect( - updatedTestOrg?.pinnedPosts - .map((id) => id.toString()) - .includes(createdPost?._id.toString()), - ).toBeTruthy(); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${PLEASE_PROVIDE_TITLE.MESSAGE}`, + }); }); - it(`creates the post and returns it when image or video is not provided`, async () => { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?.id, - text: "text", - videoUrl: "videoUrl", - title: "title", + it("should throw error if title exceeds maximum length", async () => { + const req = { + userId: testUser?.id, + body: { + organizationId: testOrganization?._id, + title: "a".repeat(257), + text: "Test post", pinned: true, }, - }; + } as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await createPost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, + }); + }); - const context = { + it("should throw error if text exceeds maximum length", async () => { + const req = { userId: testUser?.id, - }; + body: { + organizationId: testOrganization?._id, + title: "Test title", + text: "a".repeat(501), + pinned: true, + }, + } as InterfaceAuthenticatedRequest; - expect(args.data.pinned).toBe(true); + const res = mockResponse(); + await createPost(req, res); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, + }); + }); + + it("should successfully create a regular post", async () => { + const req = { + userId: testUser?.id, + body: { + organizationId: testOrganization?._id, + text: "Test post", + }, + } as InterfaceAuthenticatedRequest; - const createPostPayload = await createPostResolver?.({}, args, context); - expect(createPostPayload?.pinned).toBe(true); + const res = mockResponse(); + await createPost(req, res); - expect(createPostPayload).toEqual( + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith( expect.objectContaining({ - title: "title", - videoUrl: null, // Update the expected value to match the received value - creatorId: testUser?._id, - organization: testOrganization?._id, - imageUrl: null, + post: expect.objectContaining({ + text: "Test post", + pinned: false, + }), }), ); }); - it(`creates the post and and returns it when an image is provided`, async () => { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?.id, - text: "text", - title: "title", + it("should successfully create a pinned post", async () => { + const req = { + userId: testUser?.id, + body: { + organizationId: testOrganization?._id, + title: "Test pinned post", + text: "Test post content", pinned: true, }, - file: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZSURBVBhXYzxz5sx/BiBgefLkCQMbGxsDAEdkBicg9wbaAAAAAElFTkSuQmCC", // Provide a supported file type - }; + } as InterfaceAuthenticatedRequest; - vi.spyOn(uploadEncodedImage, "uploadEncodedImage").mockImplementation( - async (encodedImageURL: string) => encodedImageURL, - ); - - const context = { - userId: testUser?.id, - apiRootUrl: BASE_URL, - }; + const res = mockResponse(); + await createPost(req, res); - expect(args.data.pinned).toBe(true); - - const createPostPayload = await createPostResolverImage?.( - {}, - args, - context, + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + post: expect.objectContaining({ + title: "Test pinned post", + text: "Test post content", + pinned: true, + }), + }), ); - expect(createPostPayload?.pinned).toBe(true); - - const testCreatePostPayload = await Post.findOne({ - _id: createPostPayload?._id, - imageUrl: { $ne: null }, - }).lean(); - //Ensures that the post is created and imageUrl is not null - expect(testCreatePostPayload).not.toBeNull(); + // Verify organization was updated with pinned post + const updatedOrg = await Organization.findById(testOrganization?._id); + const createdPost = await Post.findOne({ title: "Test pinned post" }); + expect(updatedOrg?.pinnedPosts).toContainEqual(createdPost?._id); }); - it(`creates the post and and returns it when a video is provided`, async () => { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?.id, - text: "text", - title: "title", - pinned: true, - }, - file: "data:video/mp4;base64,VIDEO_BASE64_DATA_HERE", // Provide a supported file type + it("should successfully create a post with file upload", async () => { + const mockFileId = new Types.ObjectId(); + const mockFileUploadResponse: InterfaceUploadedFileResponse = { + _id: mockFileId, + uri: "test/file/path", + visibility: "PUBLIC", + objectKey: "test-object-key", }; - vi.spyOn(uploadEncodedVideo, "uploadEncodedVideo").mockImplementation( - async (uploadEncodedVideo: string) => uploadEncodedVideo, + vi.spyOn(uploadFileService, "uploadFile").mockResolvedValueOnce( + mockFileUploadResponse, ); - const context = { + const req = { userId: testUser?.id, - apiRootUrl: BASE_URL, - }; + body: { + organizationId: testOrganization?._id, + text: "Test post with file", + }, + file: { + filename: "test.jpg", + mimetype: "image/jpeg", + buffer: Buffer.from("test"), + originalname: "test.jpg", + size: 1024, + }, + } as InterfaceAuthenticatedRequest; - expect(args.data.pinned).toBe(true); + const res = mockResponse(); + await createPost(req, res); - const createPostPayload = await createPostResolverImage?.( - {}, - args, - context, + expect(uploadFileService.uploadFile).toHaveBeenCalled(); + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + post: expect.objectContaining({ + text: "Test post with file", + file: mockFileId, + }), + }), ); - expect(createPostPayload?.pinned).toBe(true); - - const testCreatePostPayload = await Post.findOne({ - _id: createPostPayload?._id, - videoUrl: { $ne: null }, - }).lean(); - - //Ensures that the post is created and videoUrl is not null - expect(testCreatePostPayload).not.toBeNull(); }); - it(`creates the post and throws an error for unsupported file type`, async () => { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?.id, - text: "text", - videoUrl: "videoUrl", - title: "title", - pinned: true, - }, - file: "unsupportedFile.txt", // Provide an unsupported file type - }; + it("should handle file upload error gracefully", async () => { + vi.spyOn(uploadFileService, "uploadFile").mockRejectedValueOnce( + new Error("Upload failed"), + ); - const context = { + const req = { userId: testUser?.id, - apiRootUrl: BASE_URL, - }; + body: { + organizationId: testOrganization?._id, + text: "Test post with file", + }, + file: { + filename: "test.jpg", + mimetype: "image/jpeg", + buffer: Buffer.from("test"), + originalname: "test.jpg", + size: 1024, + }, + } as InterfaceAuthenticatedRequest; - expect(args.data.pinned).toBe(true); + const res = mockResponse(); + await createPost(req, res); - // Mock the uploadEncodedImage function to throw an error for unsupported file types - vi.spyOn(uploadEncodedImage, "uploadEncodedImage").mockImplementation( - () => { - throw new Error("Unsupported file type."); + expect(uploadFileService.uploadFile).toHaveBeenCalled(); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: "Upload failed", + }); + }); + + it("should handle invalid file type", async () => { + const req = { + userId: testUser?.id, + body: { + organizationId: testOrganization?._id, + text: "Test post with file", }, - ); + file: { + filename: "test.exe", + mimetype: "application/x-msdownload", + buffer: Buffer.from("test"), + originalname: "test.exe", + size: 1024, + }, + } as InterfaceAuthenticatedRequest; - // Ensure that an error is thrown when createPostResolverImage is called - await expect( - createPostResolverImage?.({}, args, context), - ).rejects.toThrowError("Unsupported file type."); - }); + const res = mockResponse(); + await createPost(req, res); - it(`throws String Length Validation error if title is greater than 256 characters`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, - ); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?._id, - text: "random", - videoUrl: "", - title: - "AfGtN9o7IJXH9Xr5P4CcKTWMVWKOOHTldleLrWfZcThgoX5scPE5o0jARvtVA8VhneyxXquyhWb5nluW2jtP0Ry1zIOUFYfJ6BUXvpo4vCw4GVleGBnoKwkFLp5oW9L8OsEIrjVtYBwaOtXZrkTEBySZ1prr0vFcmrSoCqrCTaChNOxL3tDoHK6h44ChFvgmoVYMSq3IzJohKtbBn68D9NfEVMEtoimkGarUnVBAOsGkKv0mIBJaCl2pnR8Xwq1cG1", - imageUrl: null, - pinned: true, - }, - }; - - const context = { - userId: testUser?.id, - }; - expect(args.data.pinned).toBe(true); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - const createdPost = await createPostResolver?.({}, args, context); - expect(createdPost?.pinned).toBe(true); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual( - `${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, - ); - } - } - }); - it(`throws String Length Validation error if text is greater than 500 characters`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, - ); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?._id, - text: "JWQPfpdkGGGKyryb86K4YN85nDj4m4F7gEAMBbMXLax73pn2okV6kpWY0EYO0XSlUc0fAlp45UCgg3s6mqsRYF9FOlzNIDFLZ1rd03Z17cdJRuvBcAmbC0imyqGdXHGDUQmVyOjDkaOLAvjhB5uDeuEqajcAPTcKpZ6LMpigXuqRAd0xGdPNXyITC03FEeKZAjjJL35cSIUeMv5eWmiFlmmm70FU1Bp6575zzBtEdyWPLflcA2GpGmmf4zvT7nfgN3NIkwQIhk9OwP8dn75YYczcYuUzLpxBu1Lyog77YlAj5DNdTIveXu9zHeC6V4EEUcPQtf1622mhdU3jZNMIAyxcAG4ErtztYYRqFs0ApUxXiQI38rmiaLcicYQgcOxpmFvqRGiSduiCprCYm90CHWbQFq4w2uhr8HhR3r9HYMIYtrRyO6C3rPXaQ7otpjuNgE0AKI57AZ4nGG1lvNwptFCY60JEndSLX9Za6XP1zkVRLaMZArQNl", - videoUrl: "", - title: "random", - imageUrl: null, - pinned: true, - }, - }; - - const context = { - userId: testUser?.id, - }; - - expect(args.data.pinned).toBe(true); - - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - - const createdPost = await createPostResolver?.({}, args, context); - expect(createdPost?.pinned).toBe(true); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual( - `${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, - ); - } - } + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${INVALID_FILE_TYPE.MESSAGE}`, + }); }); - it("throws an error if the user tries to create a post but post is not pinned", async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, - ); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?._id, - text: "text", - pinned: false, - }, - }; - - const context = { - userId: testUser?.id, - }; - - expect(args.data.pinned).toBe(false); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - const createdPost = await createPostResolver?.({}, args, context); - expect(createdPost?.pinned).toBe(false); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual( - `Cannot create post when pinned is false`, - ); - } - } - }); + it("should handle non-Error type errors with internal server error message", async () => { + // Mock User.findOne to throw a non-Error type error + vi.spyOn(Post, "create").mockImplementationOnce(() => { + throw "Some unknown error"; + }); - it("throws error if title is provided and post is not pinned", async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, - ); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?._id, - title: "Test title", - text: "Test text", - pinned: false, - }, - }; - - const context = { - userId: testUser?.id, - }; - - expect(args.data.pinned).toBe(false); - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - const createdPost = await createPostResolver?.({}, args, context); - expect(createdPost?.pinned).toBe(false); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual( - `Post needs to be pinned inorder to add a title`, - ); - } - } - }); + const req = { + userId: testUser?.id, + body: { + organizationId: testOrganization?._id, + text: "Test post", + }, + } as InterfaceAuthenticatedRequest; - it("throws error if title is not provided and post is pinned", async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, - ); - try { - const args: MutationCreatePostArgs = { - data: { - organizationId: testOrganization?._id, - title: "", - text: "Test text", - pinned: true, - }, - }; - - const context = { - userId: testUser?.id, - }; - expect(args.data.pinned).toBe(true); - - const { createPost: createPostResolver } = await import( - "../../../src/resolvers/Mutation/createPost" - ); - const createPost = await createPostResolver?.({}, args, context); - expect(createPost?.pinned).toBe(true); - } catch (error) { - if (error instanceof Error) { - expect(error.message).toEqual(`Please provide a title to pin post`); - } - } + const res = mockResponse(); + await createPost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${INTERNAL_SERVER_ERROR.MESSAGE}`, + }); }); }); diff --git a/tests/resolvers/Mutation/createVolunteerMembership.spec.ts b/tests/resolvers/Mutation/createVolunteerMembership.spec.ts new file mode 100644 index 0000000000..6ef779bbc6 --- /dev/null +++ b/tests/resolvers/Mutation/createVolunteerMembership.spec.ts @@ -0,0 +1,165 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import type { Document } from "mongoose"; +import { Types } from "mongoose"; +import type { MutationCreateVolunteerMembershipArgs } from "../../../src/types/generatedGraphQLTypes"; +import { connect, disconnect } from "../../helpers/db"; + +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; +import { + EVENT_NOT_FOUND_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../src/constants"; +import type { TestUserType } from "../../helpers/userAndOrg"; +import { createTestEvent } from "../../helpers/events"; +import type { TestEventType } from "../../helpers/events"; +import { createTestUser } from "../../helpers/user"; +import type { InterfaceEventVolunteerGroup } from "../../../src/models"; +import { createVolunteerMembership } from "../../../src/resolvers/Mutation/createVolunteerMembership"; +import type { + TestVolunteerGroupType, + TestVolunteerType, +} from "../../helpers/volunteers"; +import { createTestVolunteerAndGroup } from "../../helpers/volunteers"; + +export type TestEventVolunteerGroupType = + | (InterfaceEventVolunteerGroup & Document) + | null; + +let testUser1: TestUserType; +let testEvent: TestEventType; +let tUser: TestUserType; +let tEvent: TestEventType; +let tVolunteer: TestVolunteerType; +let tVolunteerGroup: TestVolunteerGroupType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const { requestContext } = await import("../../../src/libraries"); + vi.spyOn(requestContext, "translate").mockImplementation( + (message) => message, + ); + testUser1 = await createTestUser(); + [, , testEvent] = await createTestEvent(); + + [tUser, , tEvent, tVolunteer, tVolunteerGroup] = + await createTestVolunteerAndGroup(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Mutation -> createVolunteerMembership", () => { + afterEach(() => { + vi.doUnmock("../../../src/constants"); + vi.resetModules(); + }); + + it(`throws NotFoundError if no user exists with _id === context.userId`, async () => { + try { + const args: MutationCreateVolunteerMembershipArgs = { + data: { + event: tEvent?._id, + group: tVolunteerGroup?._id, + status: "invited", + userId: tUser?._id, + }, + }; + + const context = { + userId: new Types.ObjectId().toString(), + }; + + await createVolunteerMembership?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it(`throws NotFoundError if no volunteer user exists with _id === args.data.userId`, async () => { + try { + const args: MutationCreateVolunteerMembershipArgs = { + data: { + event: tEvent?._id, + group: tVolunteerGroup?._id, + status: "invited", + userId: new Types.ObjectId().toString(), + }, + }; + + const context = { + userId: tUser?._id, + }; + + await createVolunteerMembership?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it(`throws NotFoundError if no event exists with _id === args.data.event`, async () => { + try { + const args: MutationCreateVolunteerMembershipArgs = { + data: { + event: new Types.ObjectId().toString(), + group: tVolunteerGroup?._id, + status: "invited", + userId: tUser?._id, + }, + }; + + const context = { + userId: tUser?._id, + }; + + await createVolunteerMembership?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual(EVENT_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it(`Create Voluneer Membership when volunteer already exists`, async () => { + const args: MutationCreateVolunteerMembershipArgs = { + data: { + event: tEvent?._id, + group: tVolunteerGroup?._id, + status: "invited", + userId: tUser?._id, + }, + }; + + const context = { + userId: tUser?._id, + }; + + const mem = await createVolunteerMembership?.({}, args, context); + expect(mem?.volunteer).toEqual(tVolunteer?._id); + }); + + it(`Create Voluneer Membership when volunteer doesn't exists`, async () => { + const args: MutationCreateVolunteerMembershipArgs = { + data: { + event: testEvent?._id, + status: "invited", + userId: testUser1?._id, + }, + }; + + const context = { + userId: tUser?._id, + }; + + const mem = await createVolunteerMembership?.({}, args, context); + expect(mem?.event).toEqual(testEvent?._id); + }); +}); diff --git a/tests/resolvers/Mutation/login.spec.ts b/tests/resolvers/Mutation/login.spec.ts index 120784dce8..f8335c9782 100644 --- a/tests/resolvers/Mutation/login.spec.ts +++ b/tests/resolvers/Mutation/login.spec.ts @@ -84,6 +84,99 @@ describe("resolvers -> Mutation -> login", () => { vi.resetModules(); }); + it("throws NotFoundError if the user is not found after creating AppUserProfile", async () => { + const { requestContext } = await import("../../../src/libraries"); + + // Spy on the translate function to capture error messages + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + // Create a new user with a unique email + const newUser = await User.create({ + email: `nonexistentuser${nanoid().toLowerCase()}@gmail.com`, + password: "password", + firstName: "John", + lastName: "Doe", + }); + + // Delete the user immediately to simulate a missing user scenario after AppUserProfile creation + await User.deleteOne({ _id: newUser._id }); + + // Prepare the arguments for the login resolver + const args: MutationLoginArgs = { + data: { + email: newUser.email, + password: "password", + }, + }; + + // Call the login resolver, which should throw an error + const { login: loginResolver } = await import( + "../../../src/resolvers/Mutation/login" + ); + + await loginResolver?.({}, args, {}); + } catch (error: unknown) { + if (error instanceof Error) { + // Verify that the translate function was called with the correct error message + expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); + // Verify that the error message is correctly translated + expect(error.message).toEqual( + `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + ); + } + } + }); + + it("creates a new AppUserProfile for the user if it doesn't exist and associates it with the user", async () => { + // Create a new user without an associated AppUserProfile + const newUser = await User.create({ + email: `email${nanoid().toLowerCase()}@gmail.com`, + password: "password", + firstName: "firstName", + lastName: "lastName", + }); + + const hashedPassword = await bcrypt.hash("password", 12); + await User.updateOne( + { + _id: newUser?._id, + }, + { + $set: { + password: hashedPassword, + }, + }, + ); + + const args: MutationLoginArgs = { + data: { + email: newUser?.email, + password: "password", + }, + }; + + // Call the login resolver + const loginPayload = await loginResolver?.({}, args, {}); + + // Find the newly created AppUserProfile + const userAppProfile = await AppUserProfile.findOne({ + userId: newUser?._id, + }); + + // Check if the AppUserProfile is created and associated with the user + expect(userAppProfile).toBeDefined(); + expect(loginPayload).toEqual( + expect.objectContaining({ + user: expect.objectContaining({ + appUserProfileId: userAppProfile?._id, + }), + }), + ); + }); + it(`throws NotFoundError if no user exists with email === args.data.email`, async () => { const { requestContext } = await import("../../../src/libraries"); diff --git a/tests/resolvers/Mutation/removeDirectChat.spec.ts b/tests/resolvers/Mutation/removeDirectChat.spec.ts deleted file mode 100644 index 62bf2af6c8..0000000000 --- a/tests/resolvers/Mutation/removeDirectChat.spec.ts +++ /dev/null @@ -1,228 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { - Organization, - DirectChat, - DirectChatMessage, -} from "../../../src/models"; -import type { MutationRemoveDirectChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { - ORGANIZATION_NOT_FOUND_ERROR, - CHAT_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ADMIN, -} from "../../../src/constants"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - vi, - afterEach, -} from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { createTestDirectChat } from "../../helpers/directChat"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testDirectChat: TestDirectChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestDirectChat(); - testUser = temp[0]; - testOrganization = temp[1]; - - testDirectChat = await DirectChat.create({ - users: [testUser?._id], - creatorId: testUser?._id, - organization: testOrganization?._id, - }); - - const testDirectChatMessage = temp[2]; - - testDirectChat = await DirectChat.findOneAndUpdate( - { - _id: testDirectChat._id, - }, - { - $push: { - messages: testDirectChatMessage?._id, - }, - }, - { - new: true, - }, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> removeDirectChat", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no organization exists with _id === args.organizationId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - const args: MutationRemoveDirectChatArgs = { - chatId: "", - organizationId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - await removeDirectChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${ORGANIZATION_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws NotFoundError if no directChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - const args: MutationRemoveDirectChatArgs = { - chatId: new Types.ObjectId().toString(), - organizationId: testOrganization?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - await removeDirectChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${CHAT_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws UnauthorizedError if user with _id === context.userId is not an admin - of organization with _id === args.organizationId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveDirectChatArgs = { - chatId: testDirectChat?.id, - organizationId: testOrganization?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - await removeDirectChatResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`, - ); - - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); - } - }); - - it(`deletes the directChat with _id === args.chatId`, async () => { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveDirectChatArgs = { - chatId: testDirectChat?.id, - organizationId: testOrganization?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeDirectChat: removeDirectChatResolver } = await import( - "../../../src/resolvers/Mutation/removeDirectChat" - ); - const removeDirectChatPayload = await removeDirectChatResolver?.( - {}, - args, - context, - ); - - expect(removeDirectChatPayload).toEqual(testDirectChat?.toObject()); - - const testDeletedDirectChatMessages = await DirectChatMessage.find({ - directChatMessageBelongsTo: testDirectChat?._id, - }).lean(); - - expect(testDeletedDirectChatMessages).toEqual([]); - }); -}); diff --git a/tests/resolvers/Mutation/removeEventVolunteer.spec.ts b/tests/resolvers/Mutation/removeEventVolunteer.spec.ts index bc6aa6d891..30c8bb4142 100644 --- a/tests/resolvers/Mutation/removeEventVolunteer.spec.ts +++ b/tests/resolvers/Mutation/removeEventVolunteer.spec.ts @@ -25,6 +25,7 @@ import { createTestEvent } from "../../helpers/events"; import { EventVolunteer, EventVolunteerGroup } from "../../../src/models"; import { createTestUser } from "../../helpers/user"; import type { TestEventVolunteerGroupType } from "./createEventVolunteer.spec"; +import { removeEventVolunteer } from "../../../src/resolvers/Mutation/removeEventVolunteer"; let MONGOOSE_INSTANCE: typeof mongoose; let testUser: TestUserType; @@ -35,23 +36,27 @@ let testGroup: TestEventVolunteerGroupType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); + const { requestContext } = await import("../../../src/libraries"); + vi.spyOn(requestContext, "translate").mockImplementation( + (message) => message, + ); testUser = await createTestUser(); [eventAdminUser, , testEvent] = await createTestEvent(); testGroup = await EventVolunteerGroup.create({ - creatorId: eventAdminUser?._id, - eventId: testEvent?._id, - leaderId: eventAdminUser?._id, + creator: eventAdminUser?._id, + event: testEvent?._id, + leader: eventAdminUser?._id, name: "Test group", }); testEventVolunteer = await EventVolunteer.create({ - creatorId: eventAdminUser?._id, - userId: testUser?._id, - eventId: testEvent?._id, - groupId: testGroup._id, - isInvited: true, - isAssigned: false, + creator: eventAdminUser?._id, + user: testUser?._id, + event: testEvent?._id, + groups: [testGroup?._id], + hasAccepted: false, + isPublic: false, }); }); @@ -64,13 +69,33 @@ describe("resolvers -> Mutation -> removeEventVolunteer", () => { vi.doUnmock("../../../src/constants"); vi.resetModules(); }); - it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); + it(`removes event volunteer with _id === args.id and returns it`, async () => { + const args: MutationUpdateEventVolunteerArgs = { + id: testEventVolunteer?._id, + }; + + const context = { userId: eventAdminUser?._id }; + + const deletedVolunteer = await removeEventVolunteer?.({}, args, context); + + const updatedGroup = await EventVolunteerGroup.findOne({ + _id: testGroup?._id, + }); + + expect(updatedGroup?.volunteers.toString()).toEqual(""); + expect(deletedVolunteer).toEqual( + expect.objectContaining({ + _id: testEventVolunteer?._id, + user: testEventVolunteer?.user, + hasAccepted: testEventVolunteer?.hasAccepted, + isPublic: testEventVolunteer?.isPublic, + }), + ); + }); + + it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { try { const args: MutationUpdateEventVolunteerArgs = { id: testEventVolunteer?._id, @@ -78,25 +103,15 @@ describe("resolvers -> Mutation -> removeEventVolunteer", () => { const context = { userId: new Types.ObjectId().toString() }; - const { removeEventVolunteer: removeEventVolunteerResolver } = - await import("../../../src/resolvers/Mutation/removeEventVolunteer"); - - await removeEventVolunteerResolver?.({}, args, context); + await removeEventVolunteer?.({}, args, context); } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + `${USER_NOT_FOUND_ERROR.MESSAGE}`, ); } }); it(`throws NotFoundError if no event volunteer exists with _id === args.id`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { const args: MutationUpdateEventVolunteerArgs = { id: new Types.ObjectId().toString(), @@ -104,76 +119,35 @@ describe("resolvers -> Mutation -> removeEventVolunteer", () => { const context = { userId: testUser?._id }; - const { removeEventVolunteer: removeEventVolunteerResolver } = - await import("../../../src/resolvers/Mutation/removeEventVolunteer"); - - await removeEventVolunteerResolver?.({}, args, context); + await removeEventVolunteer?.({}, args, context); } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith( - EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE, - ); expect((error as Error).message).toEqual( - `Translated ${EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE}`, + `${EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE}`, ); } }); it(`throws UnauthorizedError if current user is not leader of group`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { + const newVolunteer = await EventVolunteer.create({ + creator: eventAdminUser?._id, + user: testUser?._id, + event: testEvent?._id, + groups: [testGroup?._id], + hasAccepted: false, + isPublic: false, + }); const args: MutationUpdateEventVolunteerArgs = { - id: testEventVolunteer?._id, + id: newVolunteer?._id.toString(), }; const context = { userId: testUser?._id }; - const { removeEventVolunteer: removeEventVolunteerResolver } = - await import("../../../src/resolvers/Mutation/removeEventVolunteer"); - - await removeEventVolunteerResolver?.({}, args, context); + await removeEventVolunteer?.({}, args, context); } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + `${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, ); } }); - - it(`removes event volunteer with _id === args.id and returns it`, async () => { - const args: MutationUpdateEventVolunteerArgs = { - id: testEventVolunteer?._id, - }; - - const context = { userId: eventAdminUser?._id }; - const { removeEventVolunteer: removeEventVolunteerResolver } = await import( - "../../../src/resolvers/Mutation/removeEventVolunteer" - ); - - const deletedVolunteer = await removeEventVolunteerResolver?.( - {}, - args, - context, - ); - - const updatedGroup = await EventVolunteerGroup.findOne({ - _id: testGroup?._id, - }); - - expect(updatedGroup?.volunteers.toString()).toEqual(""); - - expect(deletedVolunteer).toEqual( - expect.objectContaining({ - _id: testEventVolunteer?._id, - userId: testEventVolunteer?.userId, - isInvited: testEventVolunteer?.isInvited, - isAssigned: testEventVolunteer?.isAssigned, - response: testEventVolunteer?.response, - }), - ); - }); }); diff --git a/tests/resolvers/Mutation/removeEventVolunteerGroup.spec.ts b/tests/resolvers/Mutation/removeEventVolunteerGroup.spec.ts index f29ca33ecd..784afb8394 100644 --- a/tests/resolvers/Mutation/removeEventVolunteerGroup.spec.ts +++ b/tests/resolvers/Mutation/removeEventVolunteerGroup.spec.ts @@ -6,6 +6,7 @@ import { USER_NOT_FOUND_ERROR, EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, + EVENT_NOT_FOUND_ERROR, } from "../../../src/constants"; import { beforeAll, @@ -22,6 +23,7 @@ import { createTestEvent } from "../../helpers/events"; import { EventVolunteer, EventVolunteerGroup } from "../../../src/models"; import { createTestUser } from "../../helpers/user"; import type { TestEventVolunteerGroupType } from "./createEventVolunteer.spec"; +import { removeEventVolunteerGroup } from "../../../src/resolvers/Mutation/removeEventVolunteerGroup"; let MONGOOSE_INSTANCE: typeof mongoose; let testUser: TestUserType; @@ -31,23 +33,27 @@ let testGroup: TestEventVolunteerGroupType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); + const { requestContext } = await import("../../../src/libraries"); + vi.spyOn(requestContext, "translate").mockImplementation( + (message) => message, + ); testUser = await createTestUser(); [eventAdminUser, , testEvent] = await createTestEvent(); testGroup = await EventVolunteerGroup.create({ - creatorId: eventAdminUser?._id, - eventId: testEvent?._id, - leaderId: eventAdminUser?._id, + creator: eventAdminUser?._id, + event: testEvent?._id, + leader: eventAdminUser?._id, name: "Test group", }); await EventVolunteer.create({ - creatorId: eventAdminUser?._id, - userId: testUser?._id, - eventId: testEvent?._id, - groupId: testGroup._id, - isInvited: true, - isAssigned: false, + creator: eventAdminUser?._id, + user: testUser?._id, + event: testEvent?._id, + groups: [testGroup._id], + hasAccepted: false, + isPublic: false, }); }); @@ -61,12 +67,6 @@ describe("resolvers -> Mutation -> removeEventVolunteerGroup", () => { vi.resetModules(); }); it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { const args: MutationUpdateEventVolunteerArgs = { id: testGroup?._id, @@ -74,27 +74,20 @@ describe("resolvers -> Mutation -> removeEventVolunteerGroup", () => { const context = { userId: new Types.ObjectId().toString() }; - const { removeEventVolunteerGroup: removeEventVolunteerGroupResolver } = + const { removeEventVolunteerGroup: removeEventVolunteerGroup } = await import( "../../../src/resolvers/Mutation/removeEventVolunteerGroup" ); - await removeEventVolunteerGroupResolver?.({}, args, context); + await removeEventVolunteerGroup?.({}, args, context); } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + `${USER_NOT_FOUND_ERROR.MESSAGE}`, ); } }); it(`throws NotFoundError if no event volunteer group exists with _id === args.id`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { const args: MutationUpdateEventVolunteerArgs = { id: new Types.ObjectId().toString(), @@ -102,29 +95,15 @@ describe("resolvers -> Mutation -> removeEventVolunteerGroup", () => { const context = { userId: testUser?._id }; - const { removeEventVolunteerGroup: removeEventVolunteerGroupResolver } = - await import( - "../../../src/resolvers/Mutation/removeEventVolunteerGroup" - ); - - await removeEventVolunteerGroupResolver?.({}, args, context); + await removeEventVolunteerGroup?.({}, args, context); } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith( - EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, - ); expect((error as Error).message).toEqual( - `Translated ${EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE}`, + `${EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE}`, ); } }); it(`throws UnauthorizedError if current user is not an event admin`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { const args: MutationUpdateEventVolunteerArgs = { id: testGroup?._id, @@ -132,16 +111,10 @@ describe("resolvers -> Mutation -> removeEventVolunteerGroup", () => { const context = { userId: testUser?._id }; - const { removeEventVolunteerGroup: removeEventVolunteerGroupResolver } = - await import( - "../../../src/resolvers/Mutation/removeEventVolunteerGroup" - ); - - await removeEventVolunteerGroupResolver?.({}, args, context); + await removeEventVolunteerGroup?.({}, args, context); } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + `${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, ); } }); @@ -152,10 +125,8 @@ describe("resolvers -> Mutation -> removeEventVolunteerGroup", () => { }; const context = { userId: eventAdminUser?._id }; - const { removeEventVolunteerGroup: removeEventVolunteerGroupResolver } = - await import("../../../src/resolvers/Mutation/removeEventVolunteerGroup"); - const deletedVolunteerGroup = await removeEventVolunteerGroupResolver?.( + const deletedVolunteerGroup = await removeEventVolunteerGroup?.( {}, args, context, @@ -164,11 +135,34 @@ describe("resolvers -> Mutation -> removeEventVolunteerGroup", () => { expect(deletedVolunteerGroup).toEqual( expect.objectContaining({ _id: testGroup?._id, - leaderId: testGroup?.leaderId, + leader: testGroup?.leader, name: testGroup?.name, - creatorId: testGroup?.creatorId, - eventId: testGroup?.eventId, + creator: testGroup?.creator, + event: testGroup?.event, }), ); }); + + it(`throws NotFoundError if volunteerGroup.event doesn't exist`, async () => { + try { + const newGrp = await EventVolunteerGroup.create({ + creator: eventAdminUser?._id, + event: new Types.ObjectId(), + leader: eventAdminUser?._id, + name: "Test group", + }); + + const args: MutationUpdateEventVolunteerArgs = { + id: newGrp?._id.toString(), + }; + + const context = { userId: eventAdminUser?._id }; + + await removeEventVolunteerGroup?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + `${EVENT_NOT_FOUND_ERROR.MESSAGE}`, + ); + } + }); }); diff --git a/tests/resolvers/Mutation/removeFromUserTags.spec.ts b/tests/resolvers/Mutation/removeFromUserTags.spec.ts new file mode 100644 index 0000000000..76069c8c38 --- /dev/null +++ b/tests/resolvers/Mutation/removeFromUserTags.spec.ts @@ -0,0 +1,416 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import type { + MutationAssignToUserTagsArgs, + MutationRemoveFromUserTagsArgs, +} from "../../../src/types/generatedGraphQLTypes"; +import { connect, disconnect } from "../../helpers/db"; + +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; +import { + TAG_NOT_FOUND, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../src/constants"; +import { + AppUserProfile, + OrganizationTagUser, + TagUser, + User, +} from "../../../src/models"; +import type { TestUserTagType } from "../../helpers/tags"; +import { + createRootTagsWithOrg, + createTwoLevelTagsWithOrg, +} from "../../helpers/tags"; +import type { + TestOrganizationType, + TestUserType, +} from "../../helpers/userAndOrg"; +import { createTestUser } from "../../helpers/userAndOrg"; + +let MONGOOSE_INSTANCE: typeof mongoose; + +let adminUser: TestUserType; +let adminUser2: TestUserType; +let testTag2: TestUserTagType; +let testTag3: TestUserTagType; +let testTag: TestUserTagType; +let testSubTag1: TestUserTagType; +let testOrg1: TestOrganizationType; +let testOrg2: TestOrganizationType; +let randomUser1: TestUserType; +let randomUser2: TestUserType; +let randomUser3: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [adminUser, testOrg1, [testTag, testSubTag1]] = + await createTwoLevelTagsWithOrg(); + [adminUser2, testOrg2, [testTag2, testTag3]] = await createRootTagsWithOrg(2); + randomUser1 = await createTestUser(); + randomUser2 = await createTestUser(); + randomUser3 = await createTestUser(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Mutation -> removeFromUserTags", () => { + afterEach(() => { + vi.doUnmock("../../../src/constants"); + vi.resetModules(); + vi.resetAllMocks(); + }); + + it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: new Types.ObjectId().toString() }, + expectedError: USER_NOT_FOUND_ERROR.MESSAGE, + }); + }); + + it(`throws NotFoundError if no tag exists with _id === args.input.currentTagId `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: adminUser?._id, + }, + }, + context: { userId: adminUser?._id }, + expectedError: TAG_NOT_FOUND.MESSAGE, + }); + }); + + it(`throws Not Authorized Error if the current user is not a superadmin or admin of the organization `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: randomUser1?._id }, + expectedError: USER_NOT_AUTHORIZED_ERROR.MESSAGE, + }); + }); + + it(`throws NotFoundError if one of the selected tags doesn't exist `, async () => { + await testErrorScenario({ + args: { + input: { + selectedTagIds: [ + testTag?._id.toString() ?? "", + new Types.ObjectId().toString(), + ], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: adminUser?._id }, + expectedError: TAG_NOT_FOUND.MESSAGE, + }); + }); + + it("throws error if user does not have appUserProfile", async () => { + const temp = await createTestUser(); + await AppUserProfile.deleteOne({ + userId: temp?._id, + }); + + await testErrorScenario({ + args: { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: testTag?._id.toString() ?? "", + }, + }, + context: { userId: temp?._id }, + expectedError: USER_NOT_AUTHORIZED_ERROR.MESSAGE, + }); + }); + + it(`Tag removal should be successful and the tag is returned`, async () => { + // assign testTag2 to random users + await Promise.all([ + User.findOneAndUpdate( + { + _id: randomUser2?._id, + }, + { + joinedOrganizations: testOrg2, + }, + ), + User.findOneAndUpdate( + { + _id: randomUser3?._id, + }, + { + joinedOrganizations: testOrg2, + }, + ), + TagUser.create({ + userId: randomUser2?._id, + tagId: testTag2?._id, + organizationId: testTag2?.organizationId, + }), + TagUser.create({ + userId: randomUser3?._id, + tagId: testTag2?._id, + organizationId: testTag2?.organizationId, + }), + ]); + + // now assign them to a new tag with the help of assignToUserTags mutation + const assignToUserTagsArgs: MutationAssignToUserTagsArgs = { + input: { + selectedTagIds: [testTag3?._id.toString() ?? ""], + currentTagId: testTag2?._id.toString() ?? "", + }, + }; + + const assignToUserTagsContext = { + userId: adminUser2?._id, + }; + + const { assignToUserTags: assignToUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/assignToUserTags" + ); + + const assignToUserTagsPayload = await assignToUserTagsResolver?.( + {}, + assignToUserTagsArgs, + assignToUserTagsContext, + ); + + expect(assignToUserTagsPayload?._id.toString()).toEqual( + testTag2?._id.toString(), + ); + + const tagAssignedToRandomUser2 = await TagUser.exists({ + tagId: testTag3, + userId: randomUser2?._id, + }); + + const tagAssignedToRandomUser3 = await TagUser.exists({ + tagId: testTag3, + userId: randomUser3?._id, + }); + + expect(tagAssignedToRandomUser2).toBeTruthy(); + expect(tagAssignedToRandomUser3).toBeTruthy(); + + // now remove them from that tag with the help of removeFromUserTags mutation + const args: MutationRemoveFromUserTagsArgs = { + input: { + selectedTagIds: [testTag3?._id.toString() ?? ""], + currentTagId: testTag2?._id.toString() ?? "", + }, + }; + + const context = { + userId: adminUser2?._id, + }; + + const { removeFromUserTags: removeFromUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/removeFromUserTags" + ); + + const payload = await removeFromUserTagsResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(testTag2?._id.toString()); + + const tagExistsForRandomUser2 = await TagUser.exists({ + tagId: testTag3, + userId: randomUser2?._id, + }); + + const tagExistsForRandomUser3 = await TagUser.exists({ + tagId: testTag3, + userId: randomUser3?._id, + }); + + expect(tagExistsForRandomUser2).toBeFalsy(); + expect(tagExistsForRandomUser3).toBeFalsy(); + }); + + it(`Should remove all the decendent tags too and returns the current tag`, async () => { + // create a new tag with the organization + const newTestTag = await OrganizationTagUser.create({ + name: "newTestTag", + organizationId: testOrg1?._id, + }); + + // assign this new test tag to random users + await Promise.all([ + User.findOneAndUpdate( + { + _id: randomUser2?._id, + }, + { + joinedOrganizations: testOrg1, + }, + ), + User.findOneAndUpdate( + { + _id: randomUser3?._id, + }, + { + joinedOrganizations: testOrg1, + }, + ), + TagUser.create({ + userId: randomUser2?._id, + tagId: newTestTag?._id, + organizationId: newTestTag?.organizationId, + }), + TagUser.create({ + userId: randomUser3?._id, + tagId: newTestTag?._id, + organizationId: newTestTag?.organizationId, + }), + ]); + + // now assign them a new sub tag, which will automatically assign them the parent tag also + const assignToUserTagsArgs: MutationAssignToUserTagsArgs = { + input: { + selectedTagIds: [testSubTag1?._id.toString() ?? ""], + currentTagId: newTestTag?._id.toString() ?? "", + }, + }; + const assignToUserTagsContext = { + userId: adminUser?._id, + }; + + const { assignToUserTags: assignToUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/assignToUserTags" + ); + + const assignToUserTagsPayload = await assignToUserTagsResolver?.( + {}, + assignToUserTagsArgs, + assignToUserTagsContext, + ); + + expect(assignToUserTagsPayload?._id.toString()).toEqual( + newTestTag?._id.toString(), + ); + + const subTagAssignedToRandomUser2 = await TagUser.exists({ + tagId: testSubTag1?._id, + userId: randomUser2?._id, + }); + + const subTagAssignedToRandomUser3 = await TagUser.exists({ + tagId: testSubTag1?._id, + userId: randomUser3?._id, + }); + + expect(subTagAssignedToRandomUser2).toBeTruthy(); + expect(subTagAssignedToRandomUser3).toBeTruthy(); + + const ancestorTagAssignedToRandomUser2 = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: randomUser2?._id, + }); + + const ancestorTagAssignedToRandomUser3 = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: randomUser3?._id, + }); + + expect(ancestorTagAssignedToRandomUser2).toBeTruthy(); + expect(ancestorTagAssignedToRandomUser3).toBeTruthy(); + + // now remove the parent tag, which will also remove the subtags + const args: MutationRemoveFromUserTagsArgs = { + input: { + selectedTagIds: [testTag?._id.toString() ?? ""], + currentTagId: newTestTag?._id.toString() ?? "", + }, + }; + const context = { + userId: adminUser?._id, + }; + + const { removeFromUserTags: removeFromUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/removeFromUserTags" + ); + + const payload = await removeFromUserTagsResolver?.({}, args, context); + + expect(payload?._id.toString()).toEqual(newTestTag?._id.toString()); + + const subTagExistsForRandomUser2 = await TagUser.exists({ + tagId: testSubTag1?._id, + userId: randomUser2?._id, + }); + + const subTagExistsForRandomUser3 = await TagUser.exists({ + tagId: testSubTag1?._id, + userId: randomUser3?._id, + }); + + expect(subTagExistsForRandomUser2).toBeFalsy(); + expect(subTagExistsForRandomUser3).toBeFalsy(); + + const ancestorTagExistsForRandomUser2 = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: randomUser2?._id, + }); + + const ancestorTagExistsForRandomUser3 = await TagUser.exists({ + tagId: testTag?._id.toString() ?? "", + userId: randomUser3?._id, + }); + + expect(ancestorTagExistsForRandomUser2).toBeFalsy(); + expect(ancestorTagExistsForRandomUser3).toBeFalsy(); + }); +}); + +const testErrorScenario = async ({ + args, + context, + expectedError, +}: { + args: MutationRemoveFromUserTagsArgs; + context: { userId: string }; + expectedError: string; +}): Promise => { + const { requestContext } = await import("../../../src/libraries"); + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + const { removeFromUserTags: removeFromUserTagsResolver } = await import( + "../../../src/resolvers/Mutation/removeFromUserTags" + ); + await removeFromUserTagsResolver?.({}, args, context); + throw new Error("Expected error was not thrown"); + } catch (error: unknown) { + if (error instanceof Error) { + expect(error.message).toEqual(`Translated ${expectedError}`); + } else { + throw new Error("Unexpected error type"); + } + expect(spy).toHaveBeenLastCalledWith(expectedError); + } +}; diff --git a/tests/resolvers/Mutation/removeGroupChat.spec.ts b/tests/resolvers/Mutation/removeGroupChat.spec.ts deleted file mode 100644 index eb7bace2c8..0000000000 --- a/tests/resolvers/Mutation/removeGroupChat.spec.ts +++ /dev/null @@ -1,243 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { Organization, GroupChat, GroupChatMessage } from "../../../src/models"; -import type { MutationRemoveGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ADMIN, -} from "../../../src/constants"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - afterEach, - vi, -} from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { cacheOrganizations } from "../../../src/services/OrganizationCache/cacheOrganizations"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestGroupChatMessage(); - testUser = temp[0]; - testOrganization = temp[1]; - testGroupChat = temp[2]; - const testGroupChatMessage = temp[3]; - testGroupChat = await GroupChat.findOneAndUpdate( - { - _id: testGroupChat?._id, - }, - { - $push: { - messages: testGroupChatMessage?._id, - }, - }, - { - new: true, - }, - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> removeGroupChat", () => { - afterEach(() => { - vi.restoreAllMocks(); - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - const args: MutationRemoveGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - }; - - const context = { - userId: testUser?.id, - }; - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - await removeGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${CHAT_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws NotFoundError if no organization exists with _id === groupChat.organization - for field organization of groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: new Types.ObjectId().toString(), - }, - }, - ); - - const args: MutationRemoveGroupChatArgs = { - chatId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - await removeGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${ORGANIZATION_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws UnauthorizedError if current user with _id === context.userId is - not an admin of organization with _id === groupChat.organization for groupChat - with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementation((message) => `Translated ${message}`); - - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $set: { - admins: [], - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveGroupChatArgs = { - chatId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - await removeGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ADMIN.MESSAGE}`, - ); - } - }); - - it(`deletes the groupChat with _id === args.chatId and all groupChatMessages - associated to it and returns it`, async () => { - const updatedOrganization = await Organization.findOneAndUpdate( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - { - new: true, - }, - ); - - if (updatedOrganization !== null) { - await cacheOrganizations([updatedOrganization]); - } - - const args: MutationRemoveGroupChatArgs = { - chatId: testGroupChat?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const { removeGroupChat: removeGroupChatResolver } = await import( - "../../../src/resolvers/Mutation/removeGroupChat" - ); - - const removeGroupChatPayload = await removeGroupChatResolver?.( - {}, - args, - context, - ); - - expect(removeGroupChatPayload).toEqual({ - ...testGroupChat?.toObject(), - updatedAt: expect.anything(), - }); - - const testDeletedGroupChatMessages = await GroupChatMessage.find({ - groupChatMessageBelongsTo: testGroupChat?._id, - }).lean(); - - expect(testDeletedGroupChatMessages).toEqual([]); - }); -}); diff --git a/tests/resolvers/Mutation/removeOrganization.spec.ts b/tests/resolvers/Mutation/removeOrganization.spec.ts index f2dfad353c..1555db8e61 100644 --- a/tests/resolvers/Mutation/removeOrganization.spec.ts +++ b/tests/resolvers/Mutation/removeOrganization.spec.ts @@ -146,6 +146,7 @@ beforeAll(async () => { creator: testUsers[0]?._id, assignee: testUsers[1]?._id, assigner: testUsers[0]?._id, + assigneeType: "EventVolunteer", actionItemCategory: testCategory?._id, organization: testOrganization?._id, }); diff --git a/tests/resolvers/Mutation/removePost.spec.ts b/tests/resolvers/Mutation/removePost.spec.ts index 197e74b9c3..b16d32140f 100644 --- a/tests/resolvers/Mutation/removePost.spec.ts +++ b/tests/resolvers/Mutation/removePost.spec.ts @@ -18,7 +18,7 @@ import { USER_NOT_AUTHORIZED_ERROR, USER_NOT_FOUND_ERROR, } from "../../../src/constants"; -import { AppUserProfile, Post } from "../../../src/models"; +import { AppUserProfile, File, Post } from "../../../src/models"; import type { TestPostType } from "../../helpers/posts"; import { createTestPost } from "../../helpers/posts"; import type { TestUserType } from "../../helpers/userAndOrg"; @@ -149,27 +149,53 @@ describe("resolvers -> Mutation -> removePost", () => { expect(removePostPayload).toEqual(testPost?.toObject()); }); - it(`deletes the post with image with _id === args.id and returns it`, async () => { + it(`deletes the post with file and returns it when referenceCount is 1`, async () => { const { requestContext } = await import("../../../src/libraries"); + const { BUCKET_NAME } = await import("../../../src/config/minio"); + vi.spyOn(requestContext, "translate").mockImplementationOnce( (message) => `Translated ${message}`, ); - const deletePreviousImage = await import( - "../../../src/utilities/encodedImageStorage/deletePreviousImage" - ); - const deleteImageSpy = vi - .spyOn(deletePreviousImage, "deletePreviousImage") - .mockImplementation(() => { - return Promise.resolve(); - }); + + // Mock Minio deleteFile with proper return type + const minioService = await import("../../../src/REST/services/minio"); + const minioDeleteSpy = vi + .spyOn(minioService, "deleteFile") + .mockImplementation(() => + Promise.resolve({ + $metadata: { + httpStatusCode: 204, + requestId: "mock-request-id", + attempts: 1, + totalRetryDelay: 0, + }, + }), + ); const [newTestUser, , newTestPost] = await createTestPost(); + const testFile = await File.create({ + _id: new Types.ObjectId(), + fileName: "test-file.jpg", + mimeType: "image/jpeg", + size: 1024, + hash: { + value: "test-hash-value", + algorithm: "SHA-256", + }, + uri: "test-uri", + referenceCount: 1, + status: "ACTIVE", + metadata: { + objectKey: "test-object-key", + }, + }); + const updatedPost = await Post.findOneAndUpdate( { _id: newTestPost?.id }, { $set: { - imageUrl: "images/fakeImagePathimage.png", + file: testFile._id, }, }, { new: true }, @@ -189,30 +215,62 @@ describe("resolvers -> Mutation -> removePost", () => { const removePostPayload = await removePostResolver?.({}, args, context); expect(removePostPayload).toEqual(updatedPost); - expect(deleteImageSpy).toBeCalledWith("images/fakeImagePathimage.png"); + + expect(minioDeleteSpy).toHaveBeenCalledWith( + BUCKET_NAME, + testFile.metadata.objectKey, + ); + + // Verify file was deleted from database + const deletedFile = await File.findById(testFile._id); + expect(deletedFile).toBeNull(); }); - it(`deletes the post with video with _id === args.id and returns it`, async () => { + it(`decrements file referenceCount when greater than 1`, async () => { const { requestContext } = await import("../../../src/libraries"); vi.spyOn(requestContext, "translate").mockImplementationOnce( (message) => `Translated ${message}`, ); - const deletePreviousVideo = await import( - "../../../src/utilities/encodedVideoStorage/deletePreviousVideo" - ); - const deleteVideoSpy = vi - .spyOn(deletePreviousVideo, "deletePreviousVideo") - .mockImplementation(() => { - return Promise.resolve(); - }); + + // Mock Minio deleteFile with proper return type + const minioService = await import("../../../src/REST/services/minio"); + const minioDeleteSpy = vi + .spyOn(minioService, "deleteFile") + .mockImplementation(() => + Promise.resolve({ + $metadata: { + httpStatusCode: 204, + requestId: "mock-request-id", + attempts: 1, + totalRetryDelay: 0, + }, + }), + ); const [newTestUser, , newTestPost] = await createTestPost(); + const testFile = await File.create({ + _id: new Types.ObjectId(), + fileName: "test-file.jpg", + mimeType: "image/jpeg", + size: 1024, + hash: { + value: "test-hash-value", + algorithm: "SHA-256", + }, + uri: "test-uri", + referenceCount: 2, + status: "ACTIVE", + metadata: { + objectKey: "test-object-key", + }, + }); + const updatedPost = await Post.findOneAndUpdate( { _id: newTestPost?.id }, { $set: { - videoUrl: "videos/fakeVideoPathvideo.png", + file: testFile._id, }, }, { new: true }, @@ -232,9 +290,16 @@ describe("resolvers -> Mutation -> removePost", () => { const removePostPayload = await removePostResolver?.({}, args, context); expect(removePostPayload).toEqual(updatedPost); - expect(deleteVideoSpy).toBeCalledWith("videos/fakeVideoPathvideo.png"); + + // Verify minioDeleteSpy was NOT called + expect(minioDeleteSpy).not.toHaveBeenCalled(); + + // Verify referenceCount was decremented + const updatedFile = await File.findById(testFile._id); + expect(updatedFile?.referenceCount).toBe(1); }); - it("throws an error if the user does not have appUserProfile", async () => { + + it("throws an error if the user does not have appUserProfile", async () => { const { requestContext } = await import("../../../src/libraries"); vi.spyOn(requestContext, "translate").mockImplementationOnce( (message) => `Translated ${message}`, diff --git a/tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts b/tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts deleted file mode 100644 index 20a18d76d1..0000000000 --- a/tests/resolvers/Mutation/removeUserFromGroupChat.spec.ts +++ /dev/null @@ -1,228 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { User, Organization, GroupChat } from "../../../src/models"; -import type { MutationRemoveUserFromGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { removeUserFromGroupChat as removeUserFromGroupChatResolver } from "../../../src/resolvers/Mutation/removeUserFromGroupChat"; -import { - CHAT_NOT_FOUND_ERROR, - ORGANIZATION_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, -} from "../../../src/constants"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { deleteOrganizationFromCache } from "../../../src/services/OrganizationCache/deleteOrganizationFromCache"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testOrganization: TestOrganizationType; -let testGroupChat: TestGroupChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestGroupChatMessage(); - testUser = temp[0]; - testOrganization = temp[1]; - testGroupChat = temp[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> removeUserFromGroupChat", () => { - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - console.log((error as Error).message); - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws UnauthorizedError if current user with _id === context.userId is not - an admin of the organization of groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $set: { - organization: testOrganization?._id, - }, - }, - ); - - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`throws UnauthorizedError if users field of groupChat with _id === args.chatId - does not contain user with _id === args.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - await Organization.updateOne( - { - _id: testOrganization?._id, - }, - { - $push: { - admins: testUser?._id, - }, - }, - ); - - await User.updateOne( - { - _id: testUser?._id, - }, - { - $push: { - adminFor: testOrganization?._id, - }, - }, - ); - - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`removes user with _id === args.userId from users list field of groupChat - with _id === args.ChatId and returns the updated groupChat`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => `Translated ${message}`, - ); - - await GroupChat.updateOne( - { - _id: testGroupChat?._id, - }, - { - $push: { - users: testUser?._id, - }, - }, - ); - - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: testUser?.id, - }; - - const context = { - userId: testUser?.id, - }; - - const removeUserFromGroupChatPayload = - await removeUserFromGroupChatResolver?.({}, args, context); - - const testRemoveUserFromGroupChatPayload = await GroupChat.findOne({ - _id: testGroupChat?._id, - }).lean(); - - expect(removeUserFromGroupChatPayload).toEqual( - testRemoveUserFromGroupChatPayload, - ); - }); - - it(`throws NotFoundError if no organization exists for groupChat with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - - const deletedOrgaization = await Organization.findOneAndDelete({ - _id: testOrganization?._id, - }); - if (deletedOrgaization) - await deleteOrganizationFromCache(deletedOrgaization); - - try { - const args: MutationRemoveUserFromGroupChatArgs = { - chatId: testGroupChat?.id, - userId: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { removeUserFromGroupChat: removeUserFromGroupChatResolver } = - await import("../../../src/resolvers/Mutation/removeUserFromGroupChat"); - - await removeUserFromGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(ORGANIZATION_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - ORGANIZATION_NOT_FOUND_ERROR.MESSAGE, - ); - } - }); -}); diff --git a/tests/resolvers/Mutation/removeUserTag.spec.ts b/tests/resolvers/Mutation/removeUserTag.spec.ts index cb9f4e815d..7fd2375a9a 100644 --- a/tests/resolvers/Mutation/removeUserTag.spec.ts +++ b/tests/resolvers/Mutation/removeUserTag.spec.ts @@ -49,14 +49,17 @@ beforeAll(async () => { { userId: testUser?._id, tagId: rootTag?._id, + organizationId: rootTag?.organizationId, }, { userId: testUser?._id, tagId: childTag1?._id, + organizationId: childTag1?.organizationId, }, { userId: testUser?._id, tagId: childTag2?._id, + organizationId: childTag2?.organizationId, }, ]); }); diff --git a/tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts b/tests/resolvers/Mutation/sendMessageToChat.spec.ts similarity index 62% rename from tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts rename to tests/resolvers/Mutation/sendMessageToChat.spec.ts index 3b589b0226..b661488ca6 100644 --- a/tests/resolvers/Mutation/sendMessageToDirectChat.spec.ts +++ b/tests/resolvers/Mutation/sendMessageToChat.spec.ts @@ -2,15 +2,12 @@ import "dotenv/config"; import type { Document } from "mongoose"; import type mongoose from "mongoose"; import { Types } from "mongoose"; -import type { - InterfaceDirectChat, - InterfaceDirectChatMessage, -} from "../../../src/models"; -import { User, Organization, DirectChat } from "../../../src/models"; -import type { MutationSendMessageToDirectChatArgs } from "../../../src/types/generatedGraphQLTypes"; +import type { InterfaceChat, InterfaceChatMessage } from "../../../src/models"; +import { User, Organization, Chat } from "../../../src/models"; +import type { MutationSendMessageToChatArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; -import { sendMessageToDirectChat as sendMessageToDirectChatResolver } from "../../../src/resolvers/Mutation/sendMessageToDirectChat"; +import { sendMessageToChat as sendMessageToChatResolver } from "../../../src/resolvers/Mutation/sendMessageToChat"; import { CHAT_NOT_FOUND_ERROR, USER_NOT_FOUND_ERROR, @@ -29,8 +26,7 @@ import type { TestUserType } from "../../helpers/userAndOrg"; let MONGOOSE_INSTANCE: typeof mongoose; let testUsers: TestUserType[]; -let testDirectChat: InterfaceDirectChat & - Document; +let testChat: InterfaceChat & Document; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); @@ -61,11 +57,14 @@ beforeAll(async () => { }, ); - testDirectChat = await DirectChat.create({ - title: "title", + testChat = await Chat.create({ + name: "Chat", creatorId: testUsers[0]?._id, organization: testOrganization._id, users: [testUsers[0]?._id, testUsers[1]?._id], + isGroup: false, + createdAt: "23456789", + updatedAt: "23456789", }); }); @@ -73,29 +72,30 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { +describe("resolvers -> Mutation -> sendMessageToChat", () => { afterEach(async () => { vi.doUnmock("../../../src/constants"); vi.resetModules(); }); - it(`throws NotFoundError if no directChat exists with _id === args.chatId`, async () => { + it(`throws NotFoundError if no chat exists with _id === args.chatId`, async () => { const { requestContext } = await import("../../../src/libraries"); const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationSendMessageToDirectChatArgs = { + const args: MutationSendMessageToChatArgs = { chatId: new Types.ObjectId().toString(), messageContent: "", }; const context = { userId: testUsers[0]?.id }; - const { sendMessageToDirectChat: sendMessageToDirectChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToDirectChat"); + const { sendMessageToChat: sendMessageToChatResolver } = await import( + "../../../src/resolvers/Mutation/sendMessageToChat" + ); - await sendMessageToDirectChatResolver?.({}, args, context); + await sendMessageToChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); @@ -108,8 +108,8 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { .spyOn(requestContext, "translate") .mockImplementationOnce((message) => message); try { - const args: MutationSendMessageToDirectChatArgs = { - chatId: testDirectChat.id, + const args: MutationSendMessageToChatArgs = { + chatId: testChat.id, messageContent: "", }; @@ -117,20 +117,21 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { userId: new Types.ObjectId().toString(), }; - const { sendMessageToDirectChat: sendMessageToDirectChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToDirectChat"); + const { sendMessageToChat: sendMessageToChatResolver } = await import( + "../../../src/resolvers/Mutation/sendMessageToChat" + ); - await sendMessageToDirectChatResolver?.({}, args, context); + await sendMessageToChatResolver?.({}, args, context); } catch (error: unknown) { expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); } }); - it(`creates the directChatMessage and returns it`, async () => { - await DirectChat.updateOne( + it(`creates the chatMessage and returns it`, async () => { + await Chat.updateOne( { - _id: testDirectChat._id, + _id: testChat._id, }, { $push: { @@ -139,20 +140,20 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { }, ); - const args: MutationSendMessageToDirectChatArgs = { - chatId: testDirectChat.id, + const args: MutationSendMessageToChatArgs = { + chatId: testChat.id, messageContent: "messageContent", }; const pubsub = { publish: ( - _action: "MESSAGE_SENT_TO_DIRECT_CHAT", + _action: "MESSAGE_SENT_TO_CHAT", _payload: { - messageSentToDirectChat: InterfaceDirectChatMessage; + messageSentToChat: InterfaceChatMessage; }, ): { _action: string; - _payload: { messageSentToDirectChat: InterfaceDirectChatMessage }; + _payload: { messageSentToChat: InterfaceChatMessage }; } => { return { _action, _payload }; }, @@ -163,14 +164,16 @@ describe("resolvers -> Mutation -> sendMessageToDirectChat", () => { pubsub, }; - const sendMessageToDirectChatPayload = - await sendMessageToDirectChatResolver?.({}, args, context); + const sendMessageToChatPayload = await sendMessageToChatResolver?.( + {}, + args, + context, + ); - expect(sendMessageToDirectChatPayload).toEqual( + expect(sendMessageToChatPayload).toEqual( expect.objectContaining({ - directChatMessageBelongsTo: testDirectChat._id, + chatMessageBelongsTo: testChat._id, sender: testUsers[0]?._id, - receiver: testUsers[1]?._id, messageContent: "messageContent", }), ); diff --git a/tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts b/tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts deleted file mode 100644 index b9d0ee8c1a..0000000000 --- a/tests/resolvers/Mutation/sendMessageToGroupChat.spec.ts +++ /dev/null @@ -1,170 +0,0 @@ -import "dotenv/config"; -import type { Document } from "mongoose"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { - InterfaceGroupChat, - InterfaceGroupChatMessage, -} from "../../../src/models"; -import { GroupChat } from "../../../src/models"; -import type { MutationSendMessageToGroupChatArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../helpers/db"; - -import { sendMessageToGroupChat as sendMessageToGroupChatResolver } from "../../../src/resolvers/Mutation/sendMessageToGroupChat"; -import { - CHAT_NOT_FOUND_ERROR, - USER_NOT_AUTHORIZED_ERROR, - USER_NOT_FOUND_ERROR, -} from "../../../src/constants"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import type { TestUserType } from "../../helpers/userAndOrg"; -import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testUser: TestUserType; -let testGroupChat: InterfaceGroupChat & - Document; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestUserAndOrganization(); - testUser = temp[0]; - - const testOrganization = temp[1]; - - testGroupChat = await GroupChat.create({ - title: "title", - creatorId: testUser?._id, - organization: testOrganization?._id, - }); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> sendMessageToGroupChat", () => { - it(`throws NotFoundError if no groupChat exists with _id === args.chatId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToGroupChatArgs = { - chatId: new Types.ObjectId().toString(), - messageContent: "", - }; - - const context = { userId: testUser?.id }; - - const { sendMessageToGroupChat: sendMessageToGroupChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToGroupChat"); - - await sendMessageToGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(CHAT_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws NotFoundError current user with _id === context.userId does not exist`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToGroupChatArgs = { - chatId: testGroupChat.id, - messageContent: "", - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - const { sendMessageToGroupChat: sendMessageToGroupChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToGroupChat"); - - await sendMessageToGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); - } - }); - - it(`throws UnauthorizedError if users field of groupChat with _id === args.chatId - does not contain current user with _id === context.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => message); - try { - const args: MutationSendMessageToGroupChatArgs = { - chatId: testGroupChat.id, - messageContent: "", - }; - - const context = { - userId: testUser?.id, - }; - - const { sendMessageToGroupChat: sendMessageToGroupChatResolver } = - await import("../../../src/resolvers/Mutation/sendMessageToGroupChat"); - - await sendMessageToGroupChatResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } - }); - - it(`creates the groupChatMessage and returns it`, async () => { - await GroupChat.updateOne( - { - _id: testGroupChat._id, - }, - { - $push: { - users: testUser?._id, - }, - }, - ); - - const args: MutationSendMessageToGroupChatArgs = { - chatId: testGroupChat.id, - messageContent: "messageContent", - }; - - const pubsub = { - publish: ( - _action: "MESSAGE_SENT_TO_GROUP_CHAT", - _payload: { - messageSentToGroupChat: InterfaceGroupChatMessage; - }, - ): { - _action: string; - _payload: { messageSentToGroupChat: InterfaceGroupChatMessage }; - } => { - return { _action, _payload }; - }, - }; - - const context = { - userId: testUser?.id, - pubsub, - }; - - const sendMessageToGroupChatPayload = - await sendMessageToGroupChatResolver?.({}, args, context); - - expect(sendMessageToGroupChatPayload).toEqual( - expect.objectContaining({ - groupChatMessageBelongsTo: testGroupChat._id, - sender: testUser?._id, - messageContent: "messageContent", - }), - ); - }); -}); diff --git a/tests/resolvers/Mutation/unassignUserTag.spec.ts b/tests/resolvers/Mutation/unassignUserTag.spec.ts index 16ce061c8f..de0a4fd84d 100644 --- a/tests/resolvers/Mutation/unassignUserTag.spec.ts +++ b/tests/resolvers/Mutation/unassignUserTag.spec.ts @@ -228,6 +228,7 @@ describe("resolvers -> Mutation -> unassignUserTag", () => { // Assign the tag to the user await TagUser.create({ ...args.input, + organizationId: testTag?.organizationId, }); // Test the unassignUserTag resolver @@ -266,11 +267,13 @@ describe("resolvers -> Mutation -> unassignUserTag", () => { // Assign the parent and sub tag to the user await TagUser.create({ ...args.input, + organizationId: testTag?.organizationId, }); await TagUser.create({ ...args.input, tagId: testSubTag1 ? testSubTag1._id.toString() : "", + organizationId: testSubTag1?.organizationId, }); // Test the unassignUserTag resolver diff --git a/tests/resolvers/Mutation/updateActionItem.spec.ts b/tests/resolvers/Mutation/updateActionItem.spec.ts index b7406cd6fa..fc6c8eb5cd 100644 --- a/tests/resolvers/Mutation/updateActionItem.spec.ts +++ b/tests/resolvers/Mutation/updateActionItem.spec.ts @@ -5,9 +5,10 @@ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; import { ACTION_ITEM_NOT_FOUND_ERROR, EVENT_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, USER_NOT_FOUND_ERROR, - USER_NOT_MEMBER_FOR_ORGANIZATION, } from "../../../src/constants"; import { updateActionItem as updateActionItemResolver } from "../../../src/resolvers/Mutation/updateActionItem"; import type { MutationUpdateActionItemArgs } from "../../../src/types/generatedGraphQLTypes"; @@ -16,26 +17,28 @@ import type { TestOrganizationType, TestUserType, } from "../../helpers/userAndOrg"; -import { - createTestUser, - createTestUserAndOrganization, -} from "../../helpers/userAndOrg"; +import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; import { nanoid } from "nanoid"; -import { ActionItem, AppUserProfile, Event, User } from "../../../src/models"; +import { ActionItem, AppUserProfile, Event } from "../../../src/models"; import type { TestActionItemType } from "../../helpers/actionItem"; import { createTestActionItem } from "../../helpers/actionItem"; import type { TestActionItemCategoryType } from "../../helpers/actionItemCategory"; import type { TestEventType } from "../../helpers/events"; +import type { + TestVolunteerGroupType, + TestVolunteerType, +} from "../../helpers/volunteers"; +import { createTestVolunteerAndGroup } from "../../helpers/volunteers"; -let randomUser: TestUserType; -let assignedTestUser: TestUserType; let testUser: TestUserType; let testUser2: TestUserType; let testOrganization: TestOrganizationType; let testCategory: TestActionItemCategoryType; let testActionItem: TestActionItemType; let testEvent: TestEventType; +let tVolunteer: TestVolunteerType; +let tVolunteerGroup: TestVolunteerGroupType; let MONGOOSE_INSTANCE: typeof mongoose; beforeAll(async () => { @@ -45,10 +48,8 @@ beforeAll(async () => { (message) => message, ); - randomUser = await createTestUser(); - [testUser2] = await createTestUserAndOrganization(); - [testUser, testOrganization, testCategory, testActionItem, assignedTestUser] = + [testUser, testOrganization, testCategory, testActionItem] = await createTestActionItem(); testEvent = await Event.create({ @@ -63,6 +64,8 @@ beforeAll(async () => { admins: [testUser2?._id], organization: testOrganization?._id, }); + + [, , , tVolunteer, tVolunteerGroup] = await createTestVolunteerAndGroup(); }); afterAll(async () => { @@ -75,7 +78,7 @@ describe("resolvers -> Mutation -> updateActionItem", () => { const args: MutationUpdateActionItemArgs = { id: new Types.ObjectId().toString(), data: { - assigneeId: randomUser?._id, + assigneeId: tVolunteer?._id, }, }; @@ -94,7 +97,7 @@ describe("resolvers -> Mutation -> updateActionItem", () => { const args: MutationUpdateActionItemArgs = { id: new Types.ObjectId().toString(), data: { - assigneeId: randomUser?._id, + assigneeId: tVolunteer?._id, }, }; @@ -116,6 +119,7 @@ describe("resolvers -> Mutation -> updateActionItem", () => { id: testActionItem?._id, data: { assigneeId: new Types.ObjectId().toString(), + assigneeType: "EventVolunteer", }, }; @@ -125,16 +129,31 @@ describe("resolvers -> Mutation -> updateActionItem", () => { await updateActionItemResolver?.({}, args, context); } catch (error: unknown) { - expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual( + EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE, + ); } }); - it(`throws NotFoundError if the new asignee is not a member of the organization`, async () => { + it(`throws NotFoundError if no user exists with _id === args.data.assigneeId`, async () => { try { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: new Types.ObjectId().toString(), + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + }); + const args: MutationUpdateActionItemArgs = { - id: testActionItem?._id, + id: testActionItem2?._id.toString() ?? "", data: { - assigneeId: randomUser?._id, + assigneeId: new Types.ObjectId().toString(), + assigneeType: "EventVolunteerGroup", }, }; @@ -145,17 +164,83 @@ describe("resolvers -> Mutation -> updateActionItem", () => { await updateActionItemResolver?.({}, args, context); } catch (error: unknown) { expect((error as Error).message).toEqual( - USER_NOT_MEMBER_FOR_ORGANIZATION.MESSAGE, + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, ); } }); + it(`throws NotFoundError if no user exists with _id === args.data.assigneeId`, async () => { + try { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: new Types.ObjectId().toString(), + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + }); + + const args: MutationUpdateActionItemArgs = { + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: new Types.ObjectId().toString(), + assigneeType: "EventVolunteerGroup", + }, + }; + + const context = { + userId: testUser?._id, + }; + + await updateActionItemResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, + ); + } + }); + it(`throws NotFoundError if no user exists when assigneeUser (doesn't exist)`, async () => { + try { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "User", + assigneeUser: new Types.ObjectId().toString(), + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: null, + }); + + const args: MutationUpdateActionItemArgs = { + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: new Types.ObjectId().toString(), + assigneeType: "User", + }, + }; + + const context = { + userId: testUser?._id, + }; + + await updateActionItemResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); + } + }); + it(`throws NotAuthorizedError if the user is not a superadmin/orgAdmin/eventAdmin`, async () => { try { const args: MutationUpdateActionItemArgs = { id: testActionItem?._id, data: { - assigneeId: testUser?._id, + assigneeId: tVolunteer?._id, + assigneeType: "EventVolunteer", }, }; @@ -171,18 +256,280 @@ describe("resolvers -> Mutation -> updateActionItem", () => { } }); - it(`updates the action item and returns it as an admin`, async () => { + it(`throws NotAuthorizedError if the actionItem.event doesn't exist`, async () => { + try { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + event: new Types.ObjectId().toString(), + creator: testUser?._id, + assigneeType: "EventVolunteer", + assignee: new Types.ObjectId().toString(), + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + }); + + const args: MutationUpdateActionItemArgs = { + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: tVolunteer?._id, + assigneeType: "EventVolunteer", + }, + }; + + const context = { + userId: testUser2?._id, + }; + + await updateActionItemResolver?.({}, args, context); + } catch (error: unknown) { + expect((error as Error).message).toEqual(EVENT_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it(`updates the action item and sets action item as completed`, async () => { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteer", + assignee: tVolunteer?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + allottedHours: 2, + isCompleted: false, + }); + + const testActionItem3 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteer", + assignee: tVolunteer?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + allottedHours: 0, + isCompleted: false, + }); + const args: MutationUpdateActionItemArgs = { - id: testActionItem?._id, + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: tVolunteer?._id, + assigneeType: "EventVolunteer", + isCompleted: true, + }, + }; + + const args2: MutationUpdateActionItemArgs = { + id: testActionItem3?._id.toString() ?? "", + data: { + assigneeId: tVolunteer?._id, + assigneeType: "EventVolunteer", + isCompleted: true, + }, + }; + + const context = { + userId: testUser?._id, + }; + + await updateActionItemResolver?.({}, args, context); + await updateActionItemResolver?.({}, args2, context); + }); + + it(`updates the action item and sets action item as not completed`, async () => { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteer", + assignee: tVolunteer?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + allottedHours: 2, + isCompleted: true, + }); + + const testActionItem3 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteer", + assignee: tVolunteer?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + isCompleted: true, + }); + + const args: MutationUpdateActionItemArgs = { + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: tVolunteer?._id, + assigneeType: "EventVolunteer", + isCompleted: false, + }, + }; + + const args2: MutationUpdateActionItemArgs = { + id: testActionItem3?._id.toString() ?? "", + data: { + assigneeId: tVolunteer?._id, + assigneeType: "EventVolunteer", + isCompleted: false, + }, + }; + + const context = { + userId: testUser?._id, + }; + + await updateActionItemResolver?.({}, args, context); + await updateActionItemResolver?.({}, args2, context); + }); + + it(`updates the action item and sets action item as completed (Volunteer Group)`, async () => { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: tVolunteerGroup?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + allottedHours: 2, + isCompleted: false, + }); + + const testActionItem3 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: tVolunteerGroup?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + allottedHours: 0, + isCompleted: false, + }); + + const args: MutationUpdateActionItemArgs = { + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: tVolunteerGroup?._id, + assigneeType: "EventVolunteerGroup", + isCompleted: true, + }, + }; + + const args2: MutationUpdateActionItemArgs = { + id: testActionItem3?._id.toString() ?? "", data: { - assigneeId: assignedTestUser?._id, + assigneeId: tVolunteerGroup?._id, + assigneeType: "EventVolunteerGroup", + isCompleted: true, }, }; - // console.log(testUser?._id); + const context = { userId: testUser?._id, }; + await updateActionItemResolver?.({}, args, context); + await updateActionItemResolver?.({}, args2, context); + }); + + it(`updates the action item and sets action item as not completed (Volunteer Group)`, async () => { + const testActionItem2 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: tVolunteerGroup?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + allottedHours: 2, + isCompleted: true, + }); + + const testActionItem3 = await ActionItem.create({ + title: `title${nanoid().toLowerCase()}`, + description: `description${nanoid().toLowerCase()}`, + creator: testUser?._id, + assigneeType: "EventVolunteerGroup", + assigneeGroup: tVolunteerGroup?._id, + organization: testOrganization?._id, + assigner: testUser?._id, + actionItemCategory: testCategory?._id, + event: testEvent?._id, + isCompleted: true, + }); + + const args: MutationUpdateActionItemArgs = { + id: testActionItem2?._id.toString() ?? "", + data: { + assigneeId: tVolunteerGroup?._id, + assigneeType: "EventVolunteerGroup", + isCompleted: false, + }, + }; + + const args2: MutationUpdateActionItemArgs = { + id: testActionItem3?._id.toString() ?? "", + data: { + assigneeId: tVolunteerGroup?._id, + assigneeType: "EventVolunteerGroup", + isCompleted: false, + }, + }; + + const context = { + userId: testUser?._id, + }; + + await updateActionItemResolver?.({}, args, context); + await updateActionItemResolver?.({}, args2, context); + }); + + it(`updates the actionItem when the user is authorized as an eventAdmin`, async () => { + const updatedTestActionItem = await ActionItem.findOneAndUpdate( + { + _id: testActionItem?._id, + }, + { + event: testEvent?._id, + }, + { + new: true, + }, + ); + + const args: MutationUpdateActionItemArgs = { + data: { + isCompleted: true, + }, + id: updatedTestActionItem?._id.toString() ?? "", + }; + + const context = { + userId: testUser2?._id, + }; + const updatedActionItemPayload = await updateActionItemResolver?.( {}, args, @@ -191,19 +538,19 @@ describe("resolvers -> Mutation -> updateActionItem", () => { expect(updatedActionItemPayload).toEqual( expect.objectContaining({ - assignee: assignedTestUser?._id, actionItemCategory: testCategory?._id, + isCompleted: true, }), ); }); - it(`updates the action item and returns it as superadmin`, async () => { - const superAdminTestUser = await AppUserProfile.findOneAndUpdate( + it(`updates the actionItem isCompleted is undefined (EventVolunteer)`, async () => { + const updatedTestActionItem = await ActionItem.findOneAndUpdate( { - userId: randomUser?._id, + _id: testActionItem?._id, }, { - isSuperAdmin: true, + event: testEvent?._id, }, { new: true, @@ -211,14 +558,16 @@ describe("resolvers -> Mutation -> updateActionItem", () => { ); const args: MutationUpdateActionItemArgs = { - id: testActionItem?._id, data: { - assigneeId: testUser?._id, + isCompleted: undefined, + assigneeId: undefined, + assigneeType: "EventVolunteer", }, + id: updatedTestActionItem?._id.toString() ?? "", }; const context = { - userId: superAdminTestUser?.userId, + userId: testUser2?._id, }; const updatedActionItemPayload = await updateActionItemResolver?.( @@ -229,53 +578,53 @@ describe("resolvers -> Mutation -> updateActionItem", () => { expect(updatedActionItemPayload).toEqual( expect.objectContaining({ - assignee: testUser?._id, actionItemCategory: testCategory?._id, + isCompleted: true, }), ); }); - it(`throws NotFoundError if no event exists to which the action item is associated`, async () => { + it(`updates the actionItem isCompleted is undefined (EventVolunteerGroup)`, async () => { const updatedTestActionItem = await ActionItem.findOneAndUpdate( { _id: testActionItem?._id, }, { - event: new Types.ObjectId().toString(), + event: testEvent?._id, }, { new: true, }, ); - await User.updateOne( - { - _id: randomUser?._id, - }, - { - $push: { joinedOrganizations: testOrganization?._id }, + const args: MutationUpdateActionItemArgs = { + data: { + isCompleted: undefined, + assigneeId: undefined, + assigneeType: "EventVolunteerGroup", }, - ); + id: updatedTestActionItem?._id.toString() ?? "", + }; - try { - const args: MutationUpdateActionItemArgs = { - id: updatedTestActionItem?._id.toString() ?? "", - data: { - assigneeId: randomUser?._id, - }, - }; + const context = { + userId: testUser2?._id, + }; - const context = { - userId: testUser?._id, - }; + const updatedActionItemPayload = await updateActionItemResolver?.( + {}, + args, + context, + ); - await updateActionItemResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(EVENT_NOT_FOUND_ERROR.MESSAGE); - } + expect(updatedActionItemPayload).toEqual( + expect.objectContaining({ + actionItemCategory: testCategory?._id, + isCompleted: true, + }), + ); }); - it(`updates the actionItem when the user is authorized as an eventAdmin`, async () => { + it(`updates the actionItem isCompleted is undefined (User)`, async () => { const updatedTestActionItem = await ActionItem.findOneAndUpdate( { _id: testActionItem?._id, @@ -290,7 +639,9 @@ describe("resolvers -> Mutation -> updateActionItem", () => { const args: MutationUpdateActionItemArgs = { data: { - isCompleted: true, + isCompleted: undefined, + assigneeId: undefined, + assigneeType: "User", }, id: updatedTestActionItem?._id.toString() ?? "", }; @@ -312,6 +663,7 @@ describe("resolvers -> Mutation -> updateActionItem", () => { }), ); }); + it("throws error if user does not have appUserProfile", async () => { await AppUserProfile.deleteOne({ userId: testUser2?._id, diff --git a/tests/resolvers/Mutation/updateEventVolunteer.spec.ts b/tests/resolvers/Mutation/updateEventVolunteer.spec.ts index 4a749cca91..86ab7b1521 100644 --- a/tests/resolvers/Mutation/updateEventVolunteer.spec.ts +++ b/tests/resolvers/Mutation/updateEventVolunteer.spec.ts @@ -1,38 +1,29 @@ import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import type { MutationUpdateEventVolunteerArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; -import { - USER_NOT_FOUND_ERROR, - EventVolunteerResponse, - EVENT_VOLUNTEER_NOT_FOUND_ERROR, - EVENT_VOLUNTEER_INVITE_USER_MISTMATCH, -} from "../../../src/constants"; -import { - beforeAll, - afterAll, - describe, - it, - expect, - vi, - afterEach, -} from "vitest"; -import type { - TestEventType, - TestEventVolunteerType, -} from "../../helpers/events"; -import { createTestEventAndVolunteer } from "../../helpers/events"; -import { createTestUser } from "../../helpers/user"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { TestEventVolunteerType } from "../../helpers/events"; +import type { TestUserType } from "../../helpers/user"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceEventVolunteer } from "../../../src/models"; +import { updateEventVolunteer } from "../../../src/resolvers/Mutation/updateEventVolunteer"; +import { EVENT_VOLUNTEER_INVITE_USER_MISTMATCH } from "../../../src/constants"; +import { requestContext } from "../../../src/libraries"; let MONGOOSE_INSTANCE: typeof mongoose; -let testEvent: TestEventType; -let testEventVolunteer: TestEventVolunteerType; +let testUser1: TestUserType; +let testUser2: TestUserType; +let testEventVolunteer1: TestEventVolunteerType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const temp = await createTestEventAndVolunteer(); - testEvent = temp[2]; - testEventVolunteer = temp[3]; + vi.spyOn(requestContext, "translate").mockImplementation( + (message) => message, + ); + const [, , user1, user2, volunteer1] = await createVolunteerAndActions(); + + testUser1 = user1; + testUser2 = user2; + testEventVolunteer1 = volunteer1; }); afterAll(async () => { @@ -40,161 +31,55 @@ afterAll(async () => { }); describe("resolvers -> Mutation -> updateEventVolunteer", () => { - afterEach(() => { - vi.doUnmock("../../../src/constants"); - vi.resetModules(); - }); - it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - + it(`throws error if context.userId !== volunteer._id`, async () => { try { - const args: MutationUpdateEventVolunteerArgs = { - id: testEventVolunteer?._id, - data: { - response: EventVolunteerResponse.YES, + (await updateEventVolunteer?.( + {}, + { + id: testEventVolunteer1?._id, + data: { + isPublic: false, + }, }, - }; - - const context = { userId: new Types.ObjectId().toString() }; - - const { updateEventVolunteer: updateEventVolunteerResolver } = - await import("../../../src/resolvers/Mutation/updateEventVolunteer"); - - await updateEventVolunteerResolver?.({}, args, context); + { userId: testUser2?._id.toString() }, + )) as unknown as InterfaceEventVolunteer[]; } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws NotFoundError if no event volunteer exists with _id === args.id`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: MutationUpdateEventVolunteerArgs = { - id: new Types.ObjectId().toString(), - data: { - response: EventVolunteerResponse.YES, - }, - }; - - const context = { userId: testEventVolunteer?.userId }; - - const { updateEventVolunteer: updateEventVolunteerResolver } = - await import("../../../src/resolvers/Mutation/updateEventVolunteer"); - - await updateEventVolunteerResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith( - EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE, - ); - expect((error as Error).message).toEqual( - `Translated ${EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } - }); - - it(`throws ConflictError if userId of volunteer is not equal to context.userId `, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: MutationUpdateEventVolunteerArgs = { - id: testEventVolunteer?._id, - data: { - response: EventVolunteerResponse.YES, - }, - }; - - const testUser2 = await createTestUser(); - const context = { userId: testUser2?._id }; - const { updateEventVolunteer: updateEventVolunteerResolver } = - await import("../../../src/resolvers/Mutation/updateEventVolunteer"); - - await updateEventVolunteerResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith( EVENT_VOLUNTEER_INVITE_USER_MISTMATCH.MESSAGE, ); - expect((error as Error).message).toEqual( - `Translated ${EVENT_VOLUNTEER_INVITE_USER_MISTMATCH.MESSAGE}`, - ); } }); - it(`updates the Event Volunteer with _id === args.id and returns it`, async () => { - const args: MutationUpdateEventVolunteerArgs = { - id: testEventVolunteer?._id, - data: { - isAssigned: true, - response: EventVolunteerResponse.YES, - isInvited: true, - eventId: testEvent?._id, - }, - }; - - const context = { userId: testEventVolunteer?.userId }; - - const { updateEventVolunteer: updateEventVolunteerResolver } = await import( - "../../../src/resolvers/Mutation/updateEventVolunteer" - ); - - const updatedEventVolunteer = await updateEventVolunteerResolver?.( + it(`data remains same if no values are updated`, async () => { + const updatedVolunteer = (await updateEventVolunteer?.( {}, - args, - context, - ); - - expect(updatedEventVolunteer).toEqual( - expect.objectContaining({ - isAssigned: true, - response: EventVolunteerResponse.YES, - eventId: testEvent?._id, - isInvited: true, - }), + { + id: testEventVolunteer1?._id, + data: {}, + }, + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceEventVolunteer; + expect(updatedVolunteer.isPublic).toEqual(testEventVolunteer1?.isPublic); + expect(updatedVolunteer.hasAccepted).toEqual( + testEventVolunteer1?.hasAccepted, ); }); - it(`updates the Event Volunteer with _id === args.id, even if args.data is empty object`, async () => { - const t = await createTestEventAndVolunteer(); - testEventVolunteer = t[3]; - const args: MutationUpdateEventVolunteerArgs = { - id: testEventVolunteer?._id, - data: {}, - }; - - const context = { userId: testEventVolunteer?.userId }; - - const { updateEventVolunteer: updateEventVolunteerResolver } = await import( - "../../../src/resolvers/Mutation/updateEventVolunteer" - ); - - const updatedEventVolunteer = await updateEventVolunteerResolver?.( + it(`updates EventVolunteer`, async () => { + const updatedVolunteer = (await updateEventVolunteer?.( {}, - args, - context, - ); - - expect(updatedEventVolunteer).toEqual( - expect.objectContaining({ - isAssigned: testEventVolunteer?.isAssigned, - response: testEventVolunteer?.response, - eventId: testEventVolunteer?.eventId, - isInvited: testEventVolunteer?.isInvited, - }), - ); + { + id: testEventVolunteer1?._id, + data: { + isPublic: false, + hasAccepted: false, + assignments: [], + }, + }, + { userId: testUser1?._id.toString() }, + )) as unknown as InterfaceEventVolunteer; + expect(updatedVolunteer.isPublic).toEqual(false); + expect(updatedVolunteer.hasAccepted).toEqual(false); + expect(updatedVolunteer.assignments).toEqual([]); }); }); diff --git a/tests/resolvers/Mutation/updateEventVolunteerGroup.spec.ts b/tests/resolvers/Mutation/updateEventVolunteerGroup.spec.ts index 645161bec6..c735688e63 100644 --- a/tests/resolvers/Mutation/updateEventVolunteerGroup.spec.ts +++ b/tests/resolvers/Mutation/updateEventVolunteerGroup.spec.ts @@ -1,14 +1,12 @@ import type mongoose from "mongoose"; import { Types } from "mongoose"; -import type { - MutationUpdateEventVolunteerArgs, - MutationUpdateEventVolunteerGroupArgs, -} from "../../../src/types/generatedGraphQLTypes"; +import type { MutationUpdateEventVolunteerGroupArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; import { USER_NOT_FOUND_ERROR, EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, + EVENT_NOT_FOUND_ERROR, } from "../../../src/constants"; import { beforeAll, @@ -25,6 +23,8 @@ import { createTestUser } from "../../helpers/user"; import type { TestUserType } from "../../helpers/userAndOrg"; import type { TestEventVolunteerGroupType } from "./createEventVolunteer.spec"; import { EventVolunteerGroup } from "../../../src/models"; +import { requestContext } from "../../../src/libraries"; +import { updateEventVolunteerGroup } from "../../../src/resolvers/Mutation/updateEventVolunteerGroup"; let MONGOOSE_INSTANCE: typeof mongoose; let testEvent: TestEventType; @@ -35,9 +35,9 @@ beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); [eventAdminUser, , testEvent] = await createTestEvent(); testGroup = await EventVolunteerGroup.create({ - creatorId: eventAdminUser?._id, - eventId: testEvent?._id, - leaderId: eventAdminUser?._id, + creator: eventAdminUser?._id, + event: testEvent?._id, + leader: eventAdminUser?._id, name: "Test group", volunteersRequired: 2, }); @@ -54,8 +54,6 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { }); it(`throws NotFoundError if no user exists with _id === context.userId `, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => `Translated ${message}`); @@ -65,17 +63,12 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { id: testGroup?._id, data: { name: "updated name", + eventId: testEvent?._id, }, }; const context = { userId: new Types.ObjectId().toString() }; - - const { updateEventVolunteerGroup: updateEventVolunteerGroupResolver } = - await import( - "../../../src/resolvers/Mutation/updateEventVolunteerGroup" - ); - - await updateEventVolunteerGroupResolver?.({}, args, context); + await updateEventVolunteerGroup?.({}, args, context); } catch (error: unknown) { expect(spy).toHaveBeenLastCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); expect((error as Error).message).toEqual( @@ -85,8 +78,6 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { }); it(`throws NotFoundError if no event volunteer group exists with _id === args.id`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => `Translated ${message}`); @@ -96,17 +87,12 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { id: new Types.ObjectId().toString(), data: { name: "updated name", + eventId: testEvent?._id, }, }; const context = { userId: eventAdminUser?._id }; - - const { updateEventVolunteerGroup: updateEventVolunteerGroupResolver } = - await import( - "../../../src/resolvers/Mutation/updateEventVolunteerGroup" - ); - - await updateEventVolunteerGroupResolver?.({}, args, context); + await updateEventVolunteerGroup?.({}, args, context); } catch (error: unknown) { expect(spy).toHaveBeenLastCalledWith( EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, @@ -117,9 +103,31 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { } }); - it(`throws UnauthorizedError if current user is not leader of group `, async () => { - const { requestContext } = await import("../../../src/libraries"); + it(`throws NotFoundError if no event exists with _id === args.data.eventId`, async () => { + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + try { + const args: MutationUpdateEventVolunteerGroupArgs = { + id: testGroup?._id, + data: { + name: "updated name", + eventId: new Types.ObjectId().toString(), + }, + }; + + const context = { userId: eventAdminUser?._id }; + await updateEventVolunteerGroup?.({}, args, context); + } catch (error: unknown) { + expect(spy).toHaveBeenLastCalledWith(EVENT_NOT_FOUND_ERROR.MESSAGE); + expect((error as Error).message).toEqual( + `Translated ${EVENT_NOT_FOUND_ERROR.MESSAGE}`, + ); + } + }); + + it(`throws UnauthorizedError if current user is not leader of group `, async () => { const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => `Translated ${message}`); @@ -129,18 +137,14 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { id: testGroup?._id, data: { name: "updated name", + eventId: testEvent?._id, }, }; const testUser2 = await createTestUser(); const context = { userId: testUser2?._id }; - const { updateEventVolunteerGroup: updateEventVolunteerGroupResolver } = - await import( - "../../../src/resolvers/Mutation/updateEventVolunteerGroup" - ); - - await updateEventVolunteerGroupResolver?.({}, args, context); + await updateEventVolunteerGroup?.({}, args, context); } catch (error: unknown) { expect(spy).toHaveBeenLastCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); expect((error as Error).message).toEqual( @@ -160,20 +164,12 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { }; const context = { userId: eventAdminUser?._id }; - - const { updateEventVolunteerGroup: updateEventVolunteerGroupResolver } = - await import("../../../src/resolvers/Mutation/updateEventVolunteerGroup"); - - const updatedGroup = await updateEventVolunteerGroupResolver?.( - {}, - args, - context, - ); + const updatedGroup = await updateEventVolunteerGroup?.({}, args, context); expect(updatedGroup).toEqual( expect.objectContaining({ name: "updated", - eventId: testEvent?._id, + event: testEvent?._id, volunteersRequired: 10, }), ); @@ -182,35 +178,26 @@ describe("resolvers -> Mutation -> updateEventVolunteerGroup", () => { it(`updates the Event Volunteer group with _id === args.id, even if args.data is empty object`, async () => { const testGroup2 = await EventVolunteerGroup.create({ name: "test", - eventId: testEvent?._id, - creatorId: eventAdminUser?._id, + event: testEvent?._id, + creator: eventAdminUser?._id, volunteersRequired: 2, - leaderId: eventAdminUser?._id, + leader: eventAdminUser?._id, }); - const args: MutationUpdateEventVolunteerArgs = { + const args: MutationUpdateEventVolunteerGroupArgs = { id: testGroup2?._id.toString(), - data: {}, + data: { + eventId: testEvent?._id, + }, }; const context = { userId: eventAdminUser?._id }; + const updatedGroup = await updateEventVolunteerGroup?.({}, args, context); - const { updateEventVolunteerGroup: updateEventVolunteerGroupResolver } = - await import("../../../src/resolvers/Mutation/updateEventVolunteerGroup"); - - const updatedGroup = await updateEventVolunteerGroupResolver?.( - {}, - args, - context, - ); - - console.log(updatedGroup); - - console.log(); expect(updatedGroup).toEqual( expect.objectContaining({ name: testGroup2?.name, volunteersRequired: testGroup2?.volunteersRequired, - eventId: testGroup2?.eventId, + event: testGroup2?.event, }), ); }); diff --git a/tests/resolvers/Mutation/updatePost.spec.ts b/tests/resolvers/Mutation/updatePost.spec.ts index c57152dc7f..d5cd9f8589 100644 --- a/tests/resolvers/Mutation/updatePost.spec.ts +++ b/tests/resolvers/Mutation/updatePost.spec.ts @@ -1,342 +1,444 @@ import "dotenv/config"; +import type mongoose from "mongoose"; import { Types } from "mongoose"; -import { AppUserProfile, Post } from "../../../src/models"; -import type { MutationUpdatePostArgs } from "../../../src/types/generatedGraphQLTypes"; -import { connect, disconnect } from "../../../src/db"; -import { updatePost as updatePostResolver } from "../../../src/resolvers/Mutation/updatePost"; +import type { Response } from "express"; +import { connect, disconnect } from "../../helpers/db"; + +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; import { + INTERNAL_SERVER_ERROR, LENGTH_VALIDATION_ERROR, + PLEASE_PROVIDE_TITLE, + POST_NEEDS_TO_BE_PINNED, POST_NOT_FOUND_ERROR, USER_NOT_AUTHORIZED_ERROR, USER_NOT_FOUND_ERROR, } from "../../../src/constants"; -import { beforeEach, afterEach, describe, it, expect, vi } from "vitest"; +import { AppUserProfile, Post } from "../../../src/models"; +import type { + TestOrganizationType, + TestUserType, +} from "../../helpers/userAndOrg"; import { - createTestOrganizationWithAdmin, createTestUser, - type TestOrganizationType, - type TestUserType, + createTestUserAndOrganization, } from "../../helpers/userAndOrg"; - +import type { InterfaceAuthenticatedRequest } from "../../../src/middleware"; +import { updatePost } from "../../../src/REST/controllers/mutation"; +import * as fileServices from "../../../src/REST/services/file"; +import type { InterfaceUploadedFileResponse } from "../../../src/REST/services/file/uploadFile"; +import { createTestPostWithMedia } from "../../helpers/posts"; import type { TestPostType } from "../../helpers/posts"; -import { createTestPost, createTestSinglePost } from "../../helpers/posts"; + +vi.mock("../../../src/libraries/requestContext", () => ({ + translate: (message: string): string => `Translated ${message}`, +})); + +/** + * module - PostUpdateControllerTests + * description - Tests for the Post Update controller functionality in a social media/blog platform + * @packageDocumentation + * + * @remarks + * Test environment uses Vitest with MongoDB for integration testing. + * File includes mock implementations for file services and translations. + * + * Key test scenarios: + * - Media attachment management (upload/delete) + * - Post content updates (text/title/pinned status) + * - Input validation (text: 500 chars, title: 256 chars) + * - Error handling (auth, post existence, pinned post rules) + * + * @see {@link updatePost} - The controller being tested + * @see {@link InterfaceAuthenticatedRequest} - Request interface + * + * @example + * ```typescript + * npm run test updatePost.test + * ``` + */ let testUser: TestUserType; -let testPost: TestPostType; let testOrganization: TestOrganizationType; -let testPost2: TestPostType; - -beforeEach(async () => { - await connect(); - const temp = await createTestPost(true); +let testPost: TestPostType; +let MONGOOSE_INSTANCE: typeof mongoose; + +interface InterfaceMockResponse extends Omit { + status(code: number): InterfaceMockResponse; + json(data: unknown): InterfaceMockResponse; +} + +const mockResponse = (): InterfaceMockResponse => { + const res = {} as InterfaceMockResponse; + res.status = vi.fn().mockReturnValue(res); + res.json = vi.fn().mockReturnValue(res); + return res; +}; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const temp = await createTestUserAndOrganization(); testUser = temp[0]; testOrganization = temp[1]; - testPost = temp[2]; - testPost2 = await createTestSinglePost(testUser?.id, testOrganization?.id); - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementation( - (message) => message, - ); + // Create a test post + testPost = await createTestPostWithMedia(testUser?.id, testOrganization?._id); }); -afterEach(async () => { - await disconnect(); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Mutation -> updatePost", () => { - it(`throws NotFoundError if no user exists with _id === context.userId`, async () => { - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - title: "newTitle", - }, - }; - - const context = { - userId: new Types.ObjectId().toString(), - }; - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_FOUND_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, - ); - } +describe("controllers -> post -> updatePost", () => { + afterEach(() => { + vi.clearAllMocks(); }); - it(`throws NotFoundError if no post exists with _id === args.id`, async () => { - try { - const args: MutationUpdatePostArgs = { - id: new Types.ObjectId().toString(), - }; + it("should successfully update post with file", async () => { + const mockFileId = new Types.ObjectId(); + const mockFileUploadResponse: InterfaceUploadedFileResponse = { + _id: mockFileId, + uri: "test/file/path", + visibility: "PUBLIC", + objectKey: "new-test-key", + }; - const context = { - userId: testUser?._id, - }; + vi.spyOn(fileServices, "uploadFile").mockResolvedValueOnce( + mockFileUploadResponse, + ); + vi.spyOn(fileServices, "deleteFile").mockResolvedValueOnce({ + success: true, + message: "File deleted successfully.", + }); + + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "Updated text with new file", + }, + file: { + filename: "test.jpg", + mimetype: "image/jpeg", + buffer: Buffer.from("test"), + originalname: "test.jpg", + size: 1024, + }, + } as unknown as InterfaceAuthenticatedRequest; - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual(POST_NOT_FOUND_ERROR.MESSAGE); - } - }); + const res = mockResponse(); + await updatePost(req, res); - it(`throws UnauthorizedError as current user with _id === context.userId is - not an creator of post with _id === args.id`, async () => { - const testUser1 = await createTestUser(); - const testOrg1 = await createTestOrganizationWithAdmin( - testUser1?._id, - false, - false, + expect(fileServices.uploadFile).toHaveBeenCalled(); + expect(fileServices.deleteFile).toHaveBeenCalledWith( + "test-file-object-key", + testPost?.file._id.toString(), + ); + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + post: expect.objectContaining({ + text: "Updated text with new file", + file: mockFileId, + }), + }), ); - const testPost1 = await createTestSinglePost(testUser1?._id, testOrg1?._id); - - try { - const args: MutationUpdatePostArgs = { - id: testPost1?._id.toString() ?? "", - data: { - title: "newTitle", - }, - }; - - const context = { - userId: testUser1?._id, - }; - - await Post.updateOne( - { _id: testPost1?._id }, - { $set: { creatorId: new Types.ObjectId().toString() } }, - ); - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - USER_NOT_AUTHORIZED_ERROR.MESSAGE, - ); - } }); - it(`updates the post with _id === args.id and returns the updated post`, async () => { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - title: "newTitle", - text: "nextText", + it("should successfully update the title of a pinned post", async () => { + const pinnedPost = await createTestPostWithMedia( + testUser?.id, + testOrganization?.id, + true, + ); + + const req = { + userId: testUser?.id, + params: { id: pinnedPost?._id.toString() }, + body: { + title: "Updated Title", + pinned: true, }, - }; + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + post: expect.objectContaining({ + title: "Updated Title", + }), + }), + ); + }); - const context = { - userId: testUser?._id, - }; + it("should successfully update the pinned status of a post", async () => { + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + pinned: false, + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + post: expect.objectContaining({ + pinned: false, + }), + }), + ); + }); - const updatePostPayload = await updatePostResolver?.({}, args, context); + it("should throw NotFoundError if no user exists with _id === userId", async () => { + const req = { + userId: new Types.ObjectId().toString(), + params: { id: testPost?._id.toString() }, + body: { + text: "Updated text", + }, + } as unknown as InterfaceAuthenticatedRequest; - const testUpdatePostPayload = await Post.findOne({ - _id: testPost?._id, - }).lean(); + const res = mockResponse(); + await updatePost(req, res); - expect(updatePostPayload).toEqual(testUpdatePostPayload); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_FOUND_ERROR.MESSAGE}`, + }); }); - it(`updates the post with imageUrl and returns the updated post`, async () => { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - title: "newTitle", - text: "nextText", - imageUrl: - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZSURBVBhXYzxz5sx/BiBgefLkCQMbGxsDAEdkBicg9wbaAAAAAElFTkSuQmCC", + + it("should throw NotFoundError if post does not exist", async () => { + const req = { + userId: testUser?.id, + params: { id: new Types.ObjectId().toString() }, + body: { + text: "Updated text", }, - }; + } as unknown as InterfaceAuthenticatedRequest; - const context = { - userId: testUser?._id, - }; + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${POST_NOT_FOUND_ERROR.MESSAGE}`, + }); + }); + + it("should throw UnauthorizedError if AppUserProfile is not found", async () => { + const userWithoutProfileId = await createTestUser(); + await AppUserProfile.findByIdAndDelete( + userWithoutProfileId?.appUserProfileId, + ); - const updatePostPayload = await updatePostResolver?.({}, args, context); + const req = { + userId: userWithoutProfileId?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "Updated text", + }, + } as unknown as InterfaceAuthenticatedRequest; - const testUpdatePostPayload = await Post.findOne({ - _id: testPost?._id, - }).lean(); + const res = mockResponse(); + await updatePost(req, res); - expect(updatePostPayload).toEqual(testUpdatePostPayload); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + }); }); - it(`updates the post with videoUrl and returns the updated post`, async () => { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - title: "newTitle", - text: "nextText", - videoUrl: "data:video/mp4;base64,VIDEO_BASE64_DATA_HERE", + + it("should throw UnauthorizedError if user is not authorized to update post", async () => { + const [unauthorizedUser] = await createTestUserAndOrganization(); + + const req = { + userId: unauthorizedUser?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "Unauthorized update", }, - }; + } as unknown as InterfaceAuthenticatedRequest; - const context = { - userId: testUser?._id, - }; + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, + }); + }); - const updatePostPayload = await updatePostResolver?.({}, args, context); + it("should throw error if trying to add title to unpinned post", async () => { + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + title: "New Title", + }, + } as unknown as InterfaceAuthenticatedRequest; - const testUpdatePostPayload = await Post.findOne({ - _id: testPost?._id, - }).lean(); + const res = mockResponse(); + await updatePost(req, res); - expect(updatePostPayload).toEqual(testUpdatePostPayload); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${POST_NEEDS_TO_BE_PINNED.MESSAGE}`, + }); }); - it(`throws String Length Validation error if title is greater than 256 characters`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, + + it("should throw error if removing title from pinned post", async () => { + // First create a pinned post with title + const pinnedPost = await createTestPostWithMedia( + testUser?.id, + testOrganization?.id, + true, ); - try { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - text: "random", - videoUrl: "", - title: - "AfGtN9o7IJXH9Xr5P4CcKTWMVWKOOHTldleLrWfZcThgoX5scPE5o0jARvtVA8VhneyxXquyhWb5nluW2jtP0Ry1zIOUFYfJ6BUXvpo4vCw4GVleGBnoKwkFLp5oW9L8OsEIrjVtYBwaOtXZrkTEBySZ1prr0vFcmrSoCqrCTaChNOxL3tDoHK6h44ChFvgmoVYMSq3IzJohKtbBn68D9NfEVMEtoimkGarUnVBAOsGkKv0mIBJaCl2pnR8Xwq1cG1", - imageUrl: null, - }, - }; - - const context = { - userId: testUser?.id, - }; - - const { updatePost: updatePostResolver } = await import( - "../../../src/resolvers/Mutation/updatePost" - ); - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, - ); - } + const req = { + userId: testUser?.id, + params: { id: pinnedPost?.id.toString() }, + body: { + title: "", + pinned: true, + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${PLEASE_PROVIDE_TITLE.MESSAGE}`, + }); }); - it(`throws String Length Validation error if text is greater than 500 characters`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, + + it("should throw error if title exceeds maximum length", async () => { + const testPost = await createTestPostWithMedia( + testUser?.id, + testOrganization?._id, + true, ); - try { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - text: "JWQPfpdkGGGKyryb86K4YN85nDj4m4F7gEAMBbMXLax73pn2okV6kpWY0EYO0XSlUc0fAlp45UCgg3s6mqsRYF9FOlzNIDFLZ1rd03Z17cdJRuvBcAmbC0imyqGdXHGDUQmVyOjDkaOLAvjhB5uDeuEqajcAPTcKpZ6LMpigXuqRAd0xGdPNXyITC03FEeKZAjjJL35cSIUeMv5eWmiFlmmm70FU1Bp6575zzBtEdyWPLflcA2GpGmmf4zvT7nfgN3NIkwQIhk9OwP8dn75YYczcYuUzLpxBu1Lyog77YlAj5DNdTIveXu9zHeC6V4EEUcPQtf1622mhdU3jZNMIAyxcAG4ErtztYYRqFs0ApUxXiQI38rmiaLcicYQgcOxpmFvqRGiSduiCprCYm90CHWbQFq4w2uhr8HhR3r9HYMIYtrRyO6C3rPXaQ7otpjuNgE0AKI57AZ4nGG1lvNwptFCY60JEndSLX9Za6XP1zkVRLaMZArQNl", - videoUrl: "", - title: "random", - imageUrl: null, - }, - }; - - const context = { - userId: testUser?.id, - }; - - const { updatePost: updatePostResolver } = await import( - "../../../src/resolvers/Mutation/updatePost" - ); - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, - ); - } + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + title: "a".repeat(257), + pinned: true, + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${LENGTH_VALIDATION_ERROR.MESSAGE} 256 characters in title`, + }); }); - it("throws error if title is provided and post is not pinned", async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, - ); - try { - const args: MutationUpdatePostArgs = { - id: testPost2?._id.toString() || "", - data: { - title: "Test title", - text: "Test text", - }, - }; - - const context = { - userId: testUser?.id, - }; - - const { updatePost: updatePostResolver } = await import( - "../../../src/resolvers/Mutation/updatePost" - ); - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `Post needs to be pinned inorder to add a title`, - ); - } + it("should throw error if text exceeds maximum length", async () => { + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "a".repeat(501), + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${LENGTH_VALIDATION_ERROR.MESSAGE} 500 characters in information`, + }); }); - it(`throws error if title is not provided and post is pinned`, async () => { - const { requestContext } = await import("../../../src/libraries"); - vi.spyOn(requestContext, "translate").mockImplementationOnce( - (message) => message, + it("should successfully update post text", async () => { + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "Updated post text", + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(200); + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + post: expect.objectContaining({ + text: "Updated post text", + }), + }), ); - try { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - text: "Testing text", - }, - }; - - const context = { - userId: testUser?.id, - }; - - const { updatePost: updatePostResolver } = await import( - "../../../src/resolvers/Mutation/updatePost" - ); - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect((error as Error).message).toEqual( - `Please provide a title to pin post`, - ); - } }); - it("throws error if AppUserProfile is not found", async () => { - const userWithoutProfileId = await createTestUser(); - await AppUserProfile.findByIdAndDelete( - userWithoutProfileId?.appUserProfileId, + it("should handle file upload error gracefully", async () => { + vi.spyOn(fileServices, "uploadFile").mockRejectedValueOnce( + new Error("Upload failed"), ); - const { requestContext } = await import("../../../src/libraries"); - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - try { - const args: MutationUpdatePostArgs = { - id: testPost?._id.toString() || "", - data: { - title: "newTitle", - }, - }; - - const context = { - userId: userWithoutProfileId?._id, - }; - - await updatePostResolver?.({}, args, context); - } catch (error: unknown) { - expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ERROR.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${USER_NOT_AUTHORIZED_ERROR.MESSAGE}`, - ); - } + + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "Updated text with file", + }, + file: { + filename: "test.jpg", + mimetype: "image/jpeg", + buffer: Buffer.from("test"), + originalname: "test.jpg", + size: 1024, + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(fileServices.uploadFile).toHaveBeenCalled(); + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: "Upload failed", + }); + }); + + it("should handle non-Error type errors with internal server error message", async () => { + vi.spyOn(Post, "findOneAndUpdate").mockImplementationOnce(() => { + throw "Some unknown error"; + }); + + const req = { + userId: testUser?.id, + params: { id: testPost?._id.toString() }, + body: { + text: "Updated text", + }, + } as unknown as InterfaceAuthenticatedRequest; + + const res = mockResponse(); + await updatePost(req, res); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ + error: `Translated ${INTERNAL_SERVER_ERROR.MESSAGE}`, + }); }); }); diff --git a/tests/resolvers/Mutation/updateUserProfile.spec.ts b/tests/resolvers/Mutation/updateUserProfile.spec.ts index 5cfe090aa1..e3657c28b5 100644 --- a/tests/resolvers/Mutation/updateUserProfile.spec.ts +++ b/tests/resolvers/Mutation/updateUserProfile.spec.ts @@ -6,6 +6,7 @@ import type { InterfaceUser } from "../../../src/models"; import { User } from "../../../src/models"; import type { MutationUpdateUserProfileArgs } from "../../../src/types/generatedGraphQLTypes"; import { connect, disconnect } from "../../helpers/db"; +import * as userCache from "../../../src/services/UserCache/deleteUserFromCache"; import { nanoid } from "nanoid"; import { @@ -23,7 +24,6 @@ import { USER_NOT_FOUND_ERROR, } from "../../../src/constants"; import { updateUserProfile as updateUserProfileResolver } from "../../../src/resolvers/Mutation/updateUserProfile"; -import { deleteUserFromCache } from "../../../src/services/UserCache/deleteUserFromCache"; import * as uploadEncodedImage from "../../../src/utilities/encodedImageStorage/uploadEncodedImage"; let MONGOOSE_INSTANCE: typeof mongoose; @@ -302,75 +302,6 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { }); }); - it("When Image is give updates the current user's object with the uploaded image and returns it", async () => { - const args: MutationUpdateUserProfileArgs = { - data: {}, - file: "newImageFile.png", - }; - - vi.spyOn(uploadEncodedImage, "uploadEncodedImage").mockImplementation( - async (encodedImageURL: string) => encodedImageURL, - ); - - const context = { - userId: testUser._id, - apiRootUrl: BASE_URL, - }; - await deleteUserFromCache(testUser._id.toString() || ""); - - const updateUserProfilePayload = await updateUserProfileResolver?.( - {}, - args, - context, - ); - - expect(updateUserProfilePayload).toEqual({ - ...testUser.toObject(), - email: updateUserProfilePayload?.email, - firstName: "newFirstName", - lastName: "newLastName", - image: BASE_URL + "newImageFile.png", - updatedAt: expect.anything(), - createdAt: expect.anything(), - }); - }); - - it("When Image is give updates the current user's object with the uploaded image and returns it", async () => { - const args: MutationUpdateUserProfileArgs = { - data: { - email: `email${nanoid().toLowerCase()}@gmail.com`, - firstName: "newFirstName", - lastName: "newLastName", - }, - file: "newImageFile.png", - }; - - vi.spyOn(uploadEncodedImage, "uploadEncodedImage").mockImplementation( - async (encodedImageURL: string) => encodedImageURL, - ); - - const context = { - userId: testUser._id, - apiRootUrl: BASE_URL, - }; - - const updateUserProfilePayload = await updateUserProfileResolver?.( - {}, - args, - context, - ); - - expect(updateUserProfilePayload).toEqual({ - ...testUser.toObject(), - email: args.data?.email, - firstName: "newFirstName", - lastName: "newLastName", - image: BASE_URL + args.file, - updatedAt: expect.anything(), - createdAt: expect.anything(), - }); - }); - it(`updates current user's user object when any single argument(birthdate) is given w/0 changing other fields `, async () => { const args: MutationUpdateUserProfileArgs = { data: { @@ -396,7 +327,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: args.data?.birthDate, updatedAt: expect.anything(), createdAt: expect.anything(), @@ -428,7 +359,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: date, educationGrade: args.data?.educationGrade, updatedAt: expect.anything(), @@ -461,7 +392,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: date, educationGrade: "GRADUATE", employmentStatus: args.data?.employmentStatus, @@ -495,7 +426,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: date, educationGrade: "GRADUATE", employmentStatus: "FULL_TIME", @@ -530,7 +461,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: date, educationGrade: "GRADUATE", employmentStatus: "FULL_TIME", @@ -570,7 +501,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: date, educationGrade: "GRADUATE", employmentStatus: "FULL_TIME", @@ -616,7 +547,7 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { email: testUserobj?.email, firstName: testUserobj?.firstName, lastName: testUserobj?.lastName, - image: BASE_URL + "newImageFile.png", + image: null, birthDate: date, educationGrade: "GRADUATE", employmentStatus: "FULL_TIME", @@ -668,6 +599,10 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { async (encodedImageURL: string) => encodedImageURL, ); + const deleteFromCacheSpy = vi + .spyOn(userCache, "deleteUserFromCache") + .mockImplementation(async () => Promise.resolve()); + const context = { userId: testUser._id, apiRootUrl: BASE_URL, @@ -679,12 +614,15 @@ describe("resolvers -> Mutation -> updateUserProfile", () => { context, ); + expect(deleteFromCacheSpy).toHaveBeenCalledWith( + updateUserProfilePayload?._id.toString(), + ); expect(updateUserProfilePayload).toEqual({ ...testUser.toObject(), email: args.data?.email, firstName: args.data?.firstName, lastName: args.data?.lastName, - image: BASE_URL + args.file, + image: args.file, birthDate: date, educationGrade: args.data?.educationGrade, employmentStatus: args.data?.employmentStatus, diff --git a/tests/resolvers/Mutation/updateVolunteerMembership.spec.ts b/tests/resolvers/Mutation/updateVolunteerMembership.spec.ts new file mode 100644 index 0000000000..348998e37e --- /dev/null +++ b/tests/resolvers/Mutation/updateVolunteerMembership.spec.ts @@ -0,0 +1,175 @@ +import type mongoose from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import type { + TestEventType, + TestEventVolunteerGroupType, + TestEventVolunteerType, +} from "../../helpers/events"; +import { createTestUser, type TestUserType } from "../../helpers/user"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import { VolunteerMembership } from "../../../src/models"; +import { updateVolunteerMembership } from "../../../src/resolvers/Mutation/updateVolunteerMembership"; +import { Types } from "mongoose"; +import { + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../../src/constants"; +import { requestContext } from "../../../src/libraries"; +import { MembershipStatus } from "../Query/getVolunteerMembership.spec"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testEvent: TestEventType; +let testUser1: TestUserType; +let testEventVolunteer1: TestEventVolunteerType; +let testEventVolunteerGroup: TestEventVolunteerGroupType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + vi.spyOn(requestContext, "translate").mockImplementation( + (message) => message, + ); + const [, event, user1, , volunteer1, , volunteerGroup, ,] = + await createVolunteerAndActions(); + + testEvent = event; + testUser1 = user1; + testEventVolunteer1 = volunteer1; + testEventVolunteerGroup = volunteerGroup; + + await VolunteerMembership.insertMany([ + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.INVITED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + group: testEventVolunteerGroup._id, + status: MembershipStatus.REQUESTED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.ACCEPTED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.REJECTED, + }, + ]); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Mutation -> updateVolunteerMembership", () => { + it("throws NotFoundError if current User does not exist", async () => { + try { + const membership = await VolunteerMembership.findOne({ + status: MembershipStatus.REQUESTED, + group: testEventVolunteerGroup._id, + volunteer: testEventVolunteer1?._id, + }); + + await updateVolunteerMembership?.( + {}, + { + id: membership?._id.toString() ?? "", + status: MembershipStatus.ACCEPTED, + }, + { userId: new Types.ObjectId().toString() }, + ); + } catch (error: unknown) { + expect((error as Error).message).toEqual(USER_NOT_FOUND_ERROR.MESSAGE); + } + }); + + it("throws NotFoundError if VolunteerMembership does not exist", async () => { + try { + await VolunteerMembership.findOne({ + status: MembershipStatus.REQUESTED, + group: testEventVolunteerGroup._id, + volunteer: testEventVolunteer1?._id, + }); + + await updateVolunteerMembership?.( + {}, + { + id: new Types.ObjectId().toString() ?? "", + status: MembershipStatus.ACCEPTED, + }, + { userId: testUser1?._id }, + ); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR.MESSAGE, + ); + } + }); + + it("throws UnauthorizedUser Error", async () => { + try { + const membership = await VolunteerMembership.findOne({ + status: MembershipStatus.REJECTED, + volunteer: testEventVolunteer1?._id, + }); + + const randomUser = await createTestUser(); + + await updateVolunteerMembership?.( + {}, + { + id: membership?._id.toString() as string, + status: MembershipStatus.ACCEPTED, + }, + { userId: randomUser?._id.toString() as string }, + ); + } catch (error: unknown) { + expect((error as Error).message).toEqual( + USER_NOT_AUTHORIZED_ERROR.MESSAGE, + ); + } + }); + + it(`updateVolunteerMembership (with group) - set to accepted `, async () => { + const membership = await VolunteerMembership.findOne({ + status: MembershipStatus.INVITED, + volunteer: testEventVolunteer1?._id, + }); + + const updatedMembership = await updateVolunteerMembership?.( + {}, + { + id: membership?._id.toString() ?? "", + status: MembershipStatus.REJECTED, + }, + { userId: testUser1?._id }, + ); + + expect(updatedMembership?.status).toEqual(MembershipStatus.REJECTED); + }); + + it(`updateVolunteerMembership (with group) - set to accepted `, async () => { + const membership = await VolunteerMembership.findOne({ + status: MembershipStatus.REQUESTED, + group: testEventVolunteerGroup._id, + volunteer: testEventVolunteer1?._id, + }); + + const updatedMembership = await updateVolunteerMembership?.( + {}, + { + id: membership?._id.toString() ?? "", + status: MembershipStatus.ACCEPTED, + }, + { userId: testUser1?._id }, + ); + + expect(updatedMembership?.status).toEqual(MembershipStatus.ACCEPTED); + }); +}); diff --git a/tests/resolvers/Organization/image.spec.ts b/tests/resolvers/Organization/image.spec.ts index 81124c80dc..f94db31e7b 100644 --- a/tests/resolvers/Organization/image.spec.ts +++ b/tests/resolvers/Organization/image.spec.ts @@ -66,7 +66,7 @@ describe("resolvers -> Organization -> image", () => { const org = await Organization.findOne({ _id: parent._id, }); - expect(creatorPayload).toEqual("http://testdomain.com" + org?.image); + expect(creatorPayload).toEqual(org?.image); } }); it(`returns null if the image is null in the organization`, async () => { diff --git a/tests/resolvers/Organization/posts.spec.ts b/tests/resolvers/Organization/posts.spec.ts index 74bb6a8d69..a71ec1d322 100644 --- a/tests/resolvers/Organization/posts.spec.ts +++ b/tests/resolvers/Organization/posts.spec.ts @@ -70,54 +70,23 @@ describe("resolvers -> Organization -> post", () => { creatorId: testUser?._id, }).countDocuments(); - const context = { apiRootUrl: "http://example.com" }; - - const formattedPost2 = { - ...testPost2?.toObject(), - imageUrl: testPost2?.imageUrl - ? new URL(testPost2.imageUrl, context.apiRootUrl).toString() - : null, - videoUrl: testPost2?.videoUrl - ? new URL(testPost2.videoUrl, context.apiRootUrl).toString() - : null, - }; - - const formattedPost = { - ...testPost?.toObject(), - imageUrl: testPost?.imageUrl - ? new URL(testPost.imageUrl, context.apiRootUrl).toString() - : null, - videoUrl: testPost?.videoUrl - ? new URL(testPost.videoUrl, context.apiRootUrl).toString() - : null, - }; + const formattedPost2 = testPost2?.toObject(); + const formattedPost = testPost?.toObject(); expect(connection).toEqual({ edges: [ { - cursor: formattedPost2._id?.toString(), + cursor: formattedPost2?._id?.toString(), node: { ...formattedPost2, - _id: formattedPost2._id?.toString(), - imageUrl: testPost?.imageUrl - ? new URL(testPost.imageUrl, context.apiRootUrl).toString() - : null, - videoUrl: formattedPost2?.videoUrl - ? new URL(formattedPost2.videoUrl, context.apiRootUrl).toString() - : null, + _id: formattedPost2?._id?.toString(), }, }, { - cursor: formattedPost._id?.toString(), + cursor: formattedPost?._id?.toString(), node: { ...formattedPost, _id: formattedPost?._id?.toString(), - imageUrl: formattedPost?.imageUrl - ? new URL(formattedPost.imageUrl, context.apiRootUrl).toString() - : null, - videoUrl: formattedPost?.videoUrl - ? new URL(formattedPost.videoUrl, context.apiRootUrl).toString() - : null, }, }, ], @@ -165,4 +134,48 @@ describe("parseCursor function", () => { expect(result.parsedCursor).toEqual(testPost?._id.toString()); } }); + it("throws GraphQLError when an invalid cursor is provided", async () => { + const parent = { + _id: testOrganization?._id, + } as InterfaceOrganization; + + try { + await postResolver?.( + parent, + { + first: 2, + after: new Types.ObjectId().toString(), // Invalid cursor + }, + {}, + ); + // If we reach here, the test should fail because an error should have been thrown + expect(true).toBe(false); + } catch (error) { + expect(error).toBeInstanceOf(GraphQLError); + if (error instanceof GraphQLError) { + expect(error.extensions.code).toEqual("INVALID_ARGUMENTS"); + expect( + (error.extensions.errors as DefaultGraphQLArgumentError[]).length, + ).toBeGreaterThan(0); + } + } + }); + + it("successfully uses parseCursor with valid cursor", async () => { + const parent = { + _id: testOrganization?._id, + } as InterfaceOrganization; + + const connection = await postResolver?.( + parent, + { + first: 2, + after: testPost2?._id.toString(), // Valid cursor + }, + {}, + ); + + expect(connection).toBeDefined(); + expect(connection?.edges.length).toBe(1); + }); }); diff --git a/tests/resolvers/Organization/userTags.spec.ts b/tests/resolvers/Organization/userTags.spec.ts index d3d3e9b948..bc7409611a 100644 --- a/tests/resolvers/Organization/userTags.spec.ts +++ b/tests/resolvers/Organization/userTags.spec.ts @@ -12,17 +12,44 @@ import { import type { DefaultGraphQLArgumentError } from "../../../src/utilities/graphQLConnection"; import { connect, disconnect } from "../../helpers/db"; import type { TestUserTagType } from "../../helpers/tags"; -import { createRootTagsWithOrg } from "../../helpers/tags"; +import { + createRootTagsWithOrg, + createTwoLevelTagsWithOrg, +} from "../../helpers/tags"; import type { TestOrganizationType } from "../../helpers/userAndOrg"; let MONGOOSE_INSTANCE: typeof mongoose; let testUserTag1: TestUserTagType, testUserTag2: TestUserTagType; +let testRootTag: TestUserTagType, testSubTag: TestUserTagType; let testOrganization: TestOrganizationType; +let testOrganization2: TestOrganizationType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); [, testOrganization, [testUserTag1, testUserTag2]] = await createRootTagsWithOrg(2); + [, testOrganization2, [testRootTag, testSubTag]] = + await createTwoLevelTagsWithOrg(); + + testRootTag = await OrganizationTagUser.findOneAndUpdate( + { + _id: testRootTag?._id, + }, + { + name: "testRootTag", + }, + { new: true }, + ).lean(); + + testSubTag = await OrganizationTagUser.findOneAndUpdate( + { + _id: testSubTag?._id, + }, + { + name: "testSubTag", + }, + { new: true }, + ).lean(); }); afterAll(async () => { @@ -44,7 +71,7 @@ describe("userTags resolver", () => { } }); - it(`returns the expected connection object`, async () => { + it(`returns the expected connection object, i.e. all the root tags`, async () => { const parent = testOrganization?.toObject() as InterfaceOrganization; const connection = await userTagsResolver?.( @@ -85,6 +112,51 @@ describe("userTags resolver", () => { totalCount, }); }); + + it(`returns all the tags (including nested tags), if the where input is defined`, async () => { + const parent = testOrganization2?.toObject() as InterfaceOrganization; + + const connection = await userTagsResolver?.( + parent, + { + first: 2, + where: { name: { starts_with: "test" } }, + sortedBy: { id: "ASCENDING" }, + }, + {}, + ); + + const totalCount = await OrganizationTagUser.find({ + name: new RegExp("^test", "i"), + organizationId: testOrganization2?._id, + }).countDocuments(); + + expect(connection).toEqual({ + edges: [ + { + cursor: testRootTag?._id.toString(), + node: { + ...testRootTag, + _id: testRootTag?._id.toString(), + }, + }, + { + cursor: testSubTag?._id.toString(), + node: { + ...testSubTag, + _id: testSubTag?._id.toString(), + }, + }, + ], + pageInfo: { + endCursor: testSubTag?._id.toString(), + hasNextPage: false, + hasPreviousPage: false, + startCursor: testRootTag?._id.toString(), + }, + totalCount, + }); + }); }); describe("parseCursor function", () => { diff --git a/tests/resolvers/Query/actionItemsByOrganization.spec.ts b/tests/resolvers/Query/actionItemsByOrganization.spec.ts index 8437ad5cdd..36cca12583 100644 --- a/tests/resolvers/Query/actionItemsByOrganization.spec.ts +++ b/tests/resolvers/Query/actionItemsByOrganization.spec.ts @@ -1,31 +1,46 @@ -import "dotenv/config"; -import type { InterfaceActionItem } from "../../../src/models"; -import { ActionItem, ActionItemCategory } from "../../../src/models"; +import type mongoose from "mongoose"; import { connect, disconnect } from "../../helpers/db"; -import type { - ActionItemWhereInput, - ActionItemsOrderByInput, - QueryActionItemsByOrganizationArgs, -} from "../../../src/types/generatedGraphQLTypes"; -import { actionItemsByOrganization as actionItemsByOrganizationResolver } from "../../../src/resolvers/Query/actionItemsByOrganization"; import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type mongoose from "mongoose"; -import { createTestActionItems } from "../../helpers/actionItem"; -import type { - TestOrganizationType, - TestUserType, -} from "../../helpers/userAndOrg"; import type { TestEventType } from "../../helpers/events"; +import type { TestUserType } from "../../helpers/user"; +import type { TestOrganizationType } from "../../helpers/userAndOrg"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceActionItem } from "../../../src/models"; +import { ActionItem } from "../../../src/models"; +import type { TestActionItemType } from "../../helpers/actionItem"; +import { actionItemsByOrganization } from "../../../src/resolvers/Query/actionItemsByOrganization"; let MONGOOSE_INSTANCE: typeof mongoose; let testOrganization: TestOrganizationType; let testEvent: TestEventType; -let testAssigneeUser: TestUserType; +let testUser1: TestUserType; +let testActionItem1: TestActionItemType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - [, testAssigneeUser, testEvent, testOrganization] = - await createTestActionItems(); + const [organization, event, user1, , , , , actionItem1] = + await createVolunteerAndActions(); + + testOrganization = organization; + testEvent = event; + testUser1 = user1; + testActionItem1 = actionItem1; + + await ActionItem.create({ + creator: testUser1?._id, + assigner: testUser1?._id, + assigneeUser: testUser1?._id, + assigneeType: "User", + assignee: null, + assigneeGroup: null, + actionItemCategory: testActionItem1.actionItemCategory, + event: null, + organization: testOrganization?._id, + allottedHours: 2, + assignmentDate: new Date(), + dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 3000), + isCompleted: false, + }); }); afterAll(async () => { @@ -33,238 +48,37 @@ afterAll(async () => { }); describe("resolvers -> Query -> actionItemsByOrganization", () => { - it(`returns list of all action items associated with an organization in ascending order where eventId is not null`, async () => { - const orderBy: ActionItemsOrderByInput = "createdAt_ASC"; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: testEvent?._id, - orderBy, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0]).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[0]._id, - }), - ); - }); - - it(`returns list of all action items associated with an organization in ascending order where eventId is null`, async () => { - const orderBy: ActionItemsOrderByInput = "createdAt_ASC"; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: null, - orderBy, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0]).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[0]._id, - }), - ); - }); - - it(`returns list of all action items associated with an organization in descending order`, async () => { - const orderBy: ActionItemsOrderByInput = "createdAt_DESC"; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: null, - orderBy, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0]).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[0]._id, - }), + it(`actionItemsByOrganization - organizationId, eventId, assigneeName`, async () => { + const actionItems = (await actionItemsByOrganization?.( + {}, + { + organizationId: testOrganization?._id, + eventId: testEvent?._id, + where: { + categoryName: "Test Action Item Category 1", + assigneeName: testUser1?.firstName, + }, + }, + {}, + )) as unknown as InterfaceActionItem[]; + expect(actionItems[0].assigneeType).toEqual("EventVolunteer"); + expect(actionItems[0].assignee.user.firstName).toEqual( + testUser1?.firstName, ); }); - it(`returns list of all action items associated with an organization and belonging to an action item category`, async () => { - const actionItemCategories = await ActionItemCategory.find({ - organizationId: testOrganization?._id, - }); - - const actionItemCategoriesIds = actionItemCategories.map( - (category) => category._id, - ); - - const actionItemCategoryId = actionItemCategoriesIds[0]; - - const where: ActionItemWhereInput = { - actionItemCategory_id: actionItemCategoryId.toString(), - }; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - where, - }; - - const actionItemsByOrganizationPayload = - await actionItemsByOrganizationResolver?.({}, args, {}); - - const actionItemsByOrganizationInfo = await ActionItem.find({ - actionItemCategoryId, - }).lean(); - - expect(actionItemsByOrganizationPayload).toEqual( - actionItemsByOrganizationInfo, - ); - }); - it(`returns list of all action items associated with an organization that are active`, async () => { - const where: ActionItemWhereInput = { - is_completed: false, - }; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: testEvent?._id, - where, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0]).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[1]._id, - }), - ); - }); - - it(`returns list of all action items associated with an organization that are completed`, async () => { - const where: ActionItemWhereInput = { - is_completed: true, - }; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: testEvent?._id, - where, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0]).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[0]._id, - }), - ); - }); - - it(`returns list of all action items matching categoryName Filter`, async () => { - const where: ActionItemWhereInput = { - categoryName: "Default", - }; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: testEvent?._id, - where, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0].actionItemCategory).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[0].actionItemCategory, - }), - ); - }); - - it(`returns list of all action items matching assigneeName Filter`, async () => { - const where: ActionItemWhereInput = { - assigneeName: testAssigneeUser?.firstName, - }; - - const args: QueryActionItemsByOrganizationArgs = { - organizationId: testOrganization?._id, - eventId: testEvent?._id, - where, - }; - - const actionItemsByOrganizationPayload = - (await actionItemsByOrganizationResolver?.( - {}, - args, - {}, - )) as InterfaceActionItem[]; - - const actionItemsByOrganizationInfo = await ActionItem.find({ - organization: args.organizationId, - event: args.eventId, - }).lean(); - - expect(actionItemsByOrganizationPayload[0].assignee).toEqual( - expect.objectContaining({ - _id: actionItemsByOrganizationInfo[0].assignee, - }), - ); + it(`actionItemsByOrganization - organizationId, assigneeName`, async () => { + const actionItems = (await actionItemsByOrganization?.( + {}, + { + organizationId: testOrganization?._id, + where: { + assigneeName: testUser1?.firstName, + }, + }, + {}, + )) as unknown as InterfaceActionItem[]; + expect(actionItems[0].assigneeType).toEqual("User"); + expect(actionItems[0].assigneeUser.firstName).toEqual(testUser1?.firstName); }); }); diff --git a/tests/resolvers/Query/actionItemsByUser.spec.ts b/tests/resolvers/Query/actionItemsByUser.spec.ts new file mode 100644 index 0000000000..e5929381b6 --- /dev/null +++ b/tests/resolvers/Query/actionItemsByUser.spec.ts @@ -0,0 +1,98 @@ +import type mongoose from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { TestUserType } from "../../helpers/user"; +import type { TestOrganizationType } from "../../helpers/userAndOrg"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceActionItem } from "../../../src/models"; +import { ActionItem } from "../../../src/models"; +import type { TestActionItemType } from "../../helpers/actionItem"; +import { actionItemsByUser } from "../../../src/resolvers/Query/actionItemsByUser"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testOrganization: TestOrganizationType; +let testUser1: TestUserType; +let testActionItem1: TestActionItemType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const [organization, , user1, , , , , actionItem1] = + await createVolunteerAndActions(); + + testOrganization = organization; + testUser1 = user1; + testActionItem1 = actionItem1; + + await ActionItem.create({ + creator: testUser1?._id, + assigner: testUser1?._id, + assigneeUser: testUser1?._id, + assigneeType: "User", + assignee: null, + assigneeGroup: null, + actionItemCategory: testActionItem1.actionItemCategory, + event: null, + organization: testOrganization?._id, + allottedHours: 2, + assignmentDate: new Date(), + dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 3000), + isCompleted: false, + }); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> actionItemsByUser", () => { + it(`actionItemsByUser for userId, categoryName, dueDate_ASC`, async () => { + const actionItems = (await actionItemsByUser?.( + {}, + { + userId: testUser1?._id.toString() ?? "testUserId", + orderBy: "dueDate_ASC", + where: { + categoryName: "Test Action Item Category 1", + orgId: testOrganization?._id.toString(), + }, + }, + {}, + )) as unknown as InterfaceActionItem[]; + expect(actionItems[0].assigneeType).toEqual("EventVolunteer"); + expect(actionItems[1].assigneeType).toEqual("EventVolunteerGroup"); + }); + + it(`actionItemsByUser for userId, assigneeName, dueDate_DESC`, async () => { + const actionItems = (await actionItemsByUser?.( + {}, + { + userId: testUser1?._id.toString() ?? "testUserId", + orderBy: "dueDate_DESC", + where: { + categoryName: "Test Action Item Category 1", + assigneeName: testUser1?.firstName, + orgId: testOrganization?._id.toString(), + }, + }, + {}, + )) as unknown as InterfaceActionItem[]; + expect(actionItems[1].assignee.user.firstName).toEqual( + testUser1?.firstName, + ); + }); + + it(`actionItemsByUser for userId, assigneeName doesn't match`, async () => { + const actionItems = (await actionItemsByUser?.( + {}, + { + userId: testUser1?._id.toString() ?? "testUserId", + where: { + assigneeName: "xyz", + orgId: testOrganization?._id.toString(), + }, + }, + {}, + )) as unknown as InterfaceActionItem[]; + expect(actionItems.length).toEqual(0); + }); +}); diff --git a/tests/resolvers/Query/chatById.spec.ts b/tests/resolvers/Query/chatById.spec.ts new file mode 100644 index 0000000000..9adb1c22ea --- /dev/null +++ b/tests/resolvers/Query/chatById.spec.ts @@ -0,0 +1,37 @@ +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import { chatById } from "../../../src/resolvers/Query/chatById"; +import { createTestChat, type TestChatType } from "../../helpers/chat"; +import { connect, disconnect } from "../../helpers/db"; +let MONGOOSE_INSTANCE: typeof mongoose; +let testChat: TestChatType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const temp = await createTestChat(); + testChat = temp[2]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); +describe("resolvers->Query->chatById", () => { + it(`returns the chat with _id === args.id`, async () => { + const args = { + id: testChat?._id?.toString() ?? "", + }; + const chatByIdPayload = await chatById?.({}, args, {}); + expect(chatByIdPayload).toEqual(testChat?.toObject()); + }); + it(`throws chat not found if chat not found for args.id`, async () => { + try { + const args = { + id: new Types.ObjectId().toString(), + }; + await chatById?.({}, args, {}); + } catch (error: unknown) { + expect((error as Error).message).toEqual("Chat not found"); + } + }); +}); diff --git a/tests/resolvers/Query/chatsByuserId.spec.ts b/tests/resolvers/Query/chatsByuserId.spec.ts new file mode 100644 index 0000000000..c07ba1dfe2 --- /dev/null +++ b/tests/resolvers/Query/chatsByuserId.spec.ts @@ -0,0 +1,54 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Types } from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; + +import { chatsByUserId as chatsByUserIdResolver } from "../../../src/resolvers/Query/chatsByUserId"; +import { Chat } from "../../../src/models"; +import type { QueryChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import { createTestChat } from "../../helpers/chat"; +import type { TestUserType } from "../../helpers/userAndOrg"; + +let testUser: TestUserType; +let MONGOOSE_INSTANCE: typeof mongoose; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const resultArray = await createTestChat(); + testUser = resultArray[0]; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> chatsByUserId", () => { + it(`throws NotFoundError if no Chats exists with chats.users + containing user with _id === args.id`, async () => { + try { + const args: QueryChatsByUserIdArgs = { + id: new Types.ObjectId().toString(), + }; + + await chatsByUserIdResolver?.({}, args, {}); + } catch (error: unknown) { + expect((error as Error).message).toEqual("Chats not found"); + } + }); + + it(`returns list of all chats with chat.users containing the user + with _id === args.id`, async () => { + const args: QueryChatsByUserIdArgs = { + id: testUser?._id, + }; + + const chatsByUserIdPayload = await chatsByUserIdResolver?.({}, args, {}); + + const chatsByUserId = await Chat.find({ + users: testUser?._id, + }).lean(); + + expect(chatsByUserIdPayload).toEqual(chatsByUserId); + }); +}); diff --git a/tests/resolvers/Query/checkAuth.spec.ts b/tests/resolvers/Query/checkAuth.spec.ts index a4539389b9..7024150f66 100644 --- a/tests/resolvers/Query/checkAuth.spec.ts +++ b/tests/resolvers/Query/checkAuth.spec.ts @@ -9,7 +9,7 @@ import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; let MONGOOSE_INSTANCE: typeof mongoose; -import { AppUserProfile, User } from "../../../src/models"; +import { AppUserProfile } from "../../../src/models"; import { createTestUser } from "../../helpers/userAndOrg"; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); @@ -44,34 +44,6 @@ describe("resolvers -> Query -> checkAuth", () => { expect(user).toEqual({ ...testUser?.toObject(), image: null }); }); - it("returns user object with image ", async () => { - let testUser = await createTestUser(); - - await User.findOneAndUpdate( - { - _id: testUser?.id, - }, - { - image: `path`, - }, - ); - - testUser = await User.findOne({ - _id: testUser?.id, - }); - - const context = { - userId: testUser?._id, - apiRootUrl: `http://localhost:3000`, - }; - - const user = await checkAuthResolver?.({}, {}, context); - - expect(user).toEqual({ - ...testUser?.toObject(), - image: `${context.apiRootUrl}${testUser?.image}`, - }); - }); it("throws error if user does not have appUserProfile", async () => { try { const testUser = await createTestUser(); diff --git a/tests/resolvers/Query/directChatById.spec.ts b/tests/resolvers/Query/directChatById.spec.ts deleted file mode 100644 index 5717c5b56c..0000000000 --- a/tests/resolvers/Query/directChatById.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { directChatById as directChatByIdResolver } from "../../../src/resolvers/Query/directChatById"; -import { DirectChat } from "../../../src/models"; -import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestDirectChat } from "../../helpers/directChat"; -import type { TestDirectChatType } from "../../helpers/directChat"; - -let testDirectChat: TestDirectChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChat(); - testDirectChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsById", () => { - it(`throws NotFoundError if no directChats exists with directChats._id === args.id`, async () => { - try { - const args: QueryDirectChatsByUserIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await directChatByIdResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("Chat not found"); - } - }); - - it(`returns list of all directChats with directChat.users containing the user - with _id === args.id`, async () => { - const args: QueryDirectChatsByUserIdArgs = { - id: testDirectChat?._id.toString() ?? "defaultString", - }; - - const directChatsByUserIdPayload = await directChatByIdResolver?.( - {}, - args, - {}, - ); - - const directChatsByUserId = await DirectChat.findById( - testDirectChat?._id, - ).lean(); - console.log(directChatsByUserIdPayload); - console.log(directChatsByUserId); - expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/directChatsByUserID.spec.ts b/tests/resolvers/Query/directChatsByUserID.spec.ts deleted file mode 100644 index 780dd529f8..0000000000 --- a/tests/resolvers/Query/directChatsByUserID.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { directChatsByUserID as directChatsByUserIDResolver } from "../../../src/resolvers/Query/directChatsByUserID"; -import { DirectChat } from "../../../src/models"; -import type { QueryDirectChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestDirectChat } from "../../helpers/directChat"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChat(); - testUser = resultArray[0]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsByUserID", () => { - it(`throws NotFoundError if no directChats exists with directChats.users - containing user with _id === args.id`, async () => { - try { - const args: QueryDirectChatsByUserIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await directChatsByUserIDResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("DirectChats not found"); - } - }); - - it(`returns list of all directChats with directChat.users containing the user - with _id === args.id`, async () => { - const args: QueryDirectChatsByUserIdArgs = { - id: testUser?._id, - }; - - const directChatsByUserIdPayload = await directChatsByUserIDResolver?.( - {}, - args, - {}, - ); - - const directChatsByUserId = await DirectChat.find({ - users: testUser?._id, - }).lean(); - - expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/directChatsMessagesByChatID.spec.ts b/tests/resolvers/Query/directChatsMessagesByChatID.spec.ts deleted file mode 100644 index 78a22efd44..0000000000 --- a/tests/resolvers/Query/directChatsMessagesByChatID.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import "dotenv/config"; -import { CHAT_NOT_FOUND_ERROR } from "../../../src/constants"; -import { directChatsMessagesByChatID as directChatsMessagesByChatIDResolver } from "../../../src/resolvers/Query/directChatsMessagesByChatID"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; - -import { DirectChatMessage } from "../../../src/models"; -import type { QueryDirectChatsMessagesByChatIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { - createTestUser, - createTestUserAndOrganization, -} from "../../helpers/userAndOrg"; -import type { TestDirectChatType } from "../../helpers/directChat"; -import { - createTestDirectChatwithUsers, - createDirectChatMessage, -} from "../../helpers/directChat"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testDirectChats: TestDirectChatType[]; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - - const [testUser1, testOrganization] = await createTestUserAndOrganization(); - const testUser2 = await createTestUser(); - - const testDirectChat1 = await createTestDirectChatwithUsers( - testUser1?._id, - testOrganization?._id, - [testUser1?._id, testUser2?._id], - ); - const testDirectChat2 = await createTestDirectChatwithUsers( - testUser2?._id, - testOrganization?._id, - [testUser2?._id], - ); - - testDirectChats = [testDirectChat1, testDirectChat2]; - await createDirectChatMessage( - testUser1?._id, - testUser2?._id, - testDirectChats[0]?._id.toString() || "", - ); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsMessagesByChatID", () => { - it(`throws NotFoundError if no directChat exists with _id === args.id`, async () => { - try { - const args: QueryDirectChatsMessagesByChatIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await directChatsMessagesByChatIDResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.DESC); - } - }); - - it(`throws NotFoundError if no directChatMessages exist - for directChat with _id === args.id`, async () => { - try { - const args: QueryDirectChatsMessagesByChatIdArgs = { - id: testDirectChats[1]?._id.toString() || "", - }; - - await directChatsMessagesByChatIDResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual(CHAT_NOT_FOUND_ERROR.DESC); - } - }); - - it(`returns list of all directChatMessages found - for directChat with _id === args.id`, async () => { - const args: QueryDirectChatsMessagesByChatIdArgs = { - id: testDirectChats[0]?._id.toString() || "", - }; - - const directChatsMessagesByChatIdPayload = - await directChatsMessagesByChatIDResolver?.({}, args, {}); - - const directChatMessagesByChatId = await DirectChatMessage.find({ - directChatMessageBelongsTo: testDirectChats[0]?._id, - }).lean(); - - expect(directChatsMessagesByChatIdPayload).toEqual( - directChatMessagesByChatId, - ); - }); -}); diff --git a/tests/resolvers/Query/eventVolunteersByEvent.spec.ts b/tests/resolvers/Query/eventVolunteersByEvent.spec.ts deleted file mode 100644 index 7c02d96f0e..0000000000 --- a/tests/resolvers/Query/eventVolunteersByEvent.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type mongoose from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; -import { eventVolunteersByEvent } from "../../../src/resolvers/Query/eventVolunteersByEvent"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import type { TestEventType } from "../../helpers/events"; -import { createTestEventAndVolunteer } from "../../helpers/events"; -import { EventVolunteer } from "../../../src/models"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testEvent: TestEventType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const temp = await createTestEventAndVolunteer(); - testEvent = temp[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Mutation -> eventVolunteersByEvent", () => { - it(`returns list of all existing event volunteers with eventId === args.id`, async () => { - const volunteersPayload = await eventVolunteersByEvent?.( - {}, - { - id: testEvent?._id, - }, - {}, - ); - - const volunteers = await EventVolunteer.find({ - eventId: testEvent?._id, - }) - .populate("userId", "-password") - .lean(); - - expect(volunteersPayload).toEqual(volunteers); - }); -}); diff --git a/tests/resolvers/Query/eventsAttendedByUser.spec.ts b/tests/resolvers/Query/eventsAttendedByUser.spec.ts new file mode 100644 index 0000000000..7ee2807417 --- /dev/null +++ b/tests/resolvers/Query/eventsAttendedByUser.spec.ts @@ -0,0 +1,62 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { Event } from "../../../src/models"; +import { connect, disconnect } from "../../helpers/db"; +import type { QueryEventsAttendedByUserArgs } from "../../../src/types/generatedGraphQLTypes"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { + TestUserType, + TestOrganizationType, +} from "../../helpers/userAndOrg"; +import { createTestUserAndOrganization } from "../../helpers/userAndOrg"; +import { createEventWithRegistrant } from "../../helpers/events"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testUser: TestUserType; +let testOrganization: TestOrganizationType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [testUser, testOrganization] = await createTestUserAndOrganization(); + + await createEventWithRegistrant(testUser?._id, testOrganization?._id, true); + await createEventWithRegistrant(testUser?._id, testOrganization?._id, true); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> eventsAttendedByUser", () => { + it(`returns list of all events attended by user sorted by ascending order of event._id if args.orderBy === 'id_ASC'`, async () => { + const args: QueryEventsAttendedByUserArgs = { + id: testUser?._id, + orderBy: "id_ASC", + }; + + const { eventsAttendedByUser } = await import( + "../../../src/resolvers/Query/eventsAttendedByUser" + ); + + const eventsAttendedByUserPayload = await eventsAttendedByUser?.( + {}, + args, + {}, + ); + + const eventsAttendedByUserInfo = await Event.find({ + registrants: { + $elemMatch: { + userId: testUser?._id, + status: "ACTIVE", + }, + }, + }) + .sort({ _id: 1 }) + .populate("creatorId", "-password") + .populate("admins", "-password") + .lean(); + + expect(eventsAttendedByUserPayload).toEqual(eventsAttendedByUserInfo); + }); +}); diff --git a/tests/resolvers/Query/eventsByOrganizationConnection.spec.ts b/tests/resolvers/Query/eventsByOrganizationConnection.spec.ts index 674ad19e97..15d1ce6492 100644 --- a/tests/resolvers/Query/eventsByOrganizationConnection.spec.ts +++ b/tests/resolvers/Query/eventsByOrganizationConnection.spec.ts @@ -40,24 +40,50 @@ beforeAll(async () => { await dropAllCollectionsFromDatabase(MONGOOSE_INSTANCE); [testUser, testOrganization] = await createTestUserAndOrganization(); const testEvent1 = await createEventWithRegistrant( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - testUser!._id.toString(), + testUser?._id.toString() ?? "defaultUserId", testOrganization?._id, true, ); const testEvent2 = await createEventWithRegistrant( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - testUser!._id.toString(), + testUser?._id.toString() ?? "defaultUserId", testOrganization?._id, false, ); const testEvent3 = await createEventWithRegistrant( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - testUser!._id.toString(), + testUser?._id.toString() ?? "defaultUserId", testOrganization?._id, false, ); - testEvents = [testEvent1, testEvent2, testEvent3]; + const testEvent4 = await createEventWithRegistrant( + testUser?._id.toString() ?? "defaultUserId", + testOrganization?._id, + false, + ); + const testEvent5 = await createEventWithRegistrant( + testUser?._id.toString() ?? "defaultUserId", + testOrganization?._id, + false, + ); + + if (testEvent4) { + const today = new Date(); + const nextWeek = addDays(today, 7); + testEvent4.startDate = nextWeek.toISOString().split("T")[0]; + testEvent4.endDate = nextWeek.toISOString().split("T")[0]; + await testEvent4.save(); + } + + if (testEvent5) { + // set endDate to today and set endTime to 1 min from now + const today = new Date(); + testEvent5.endDate = today.toISOString().split("T")[0]; + testEvent5.endTime = new Date( + today.setMinutes(today.getMinutes() + 1), + ).toISOString(); + await testEvent5.save(); + } + + testEvents = [testEvent1, testEvent2, testEvent3, testEvent4, testEvent5]; }); afterAll(async () => { @@ -639,4 +665,19 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { vi.useRealTimers(); }); + + it("fetch upcoming events for the current date", async () => { + const upcomingEvents = (await eventsByOrganizationConnectionResolver?.( + {}, + { + upcomingOnly: true, + where: { + organization_id: testOrganization?._id, + }, + }, + {}, + )) as unknown as InterfaceEvent[]; + expect(upcomingEvents[0]?._id).toEqual(testEvents[3]?._id); + expect(upcomingEvents[1]?._id).toEqual(testEvents[4]?._id); + }); }); diff --git a/tests/resolvers/Query/getEventVolunteerGroups.spec.ts b/tests/resolvers/Query/getEventVolunteerGroups.spec.ts index a52a9a49d4..ab95e31c01 100644 --- a/tests/resolvers/Query/getEventVolunteerGroups.spec.ts +++ b/tests/resolvers/Query/getEventVolunteerGroups.spec.ts @@ -1,23 +1,52 @@ import type mongoose from "mongoose"; import { connect, disconnect } from "../../helpers/db"; -import { getEventVolunteerGroups } from "../../../src/resolvers/Query/getEventVolunteerGroups"; import { beforeAll, afterAll, describe, it, expect } from "vitest"; import type { TestEventType, TestEventVolunteerGroupType, + TestEventVolunteerType, } from "../../helpers/events"; -import { createTestEventVolunteerGroup } from "../../helpers/events"; -import type { EventVolunteerGroup } from "../../../src/types/generatedGraphQLTypes"; +import type { TestUserType } from "../../helpers/user"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceEventVolunteerGroup } from "../../../src/models"; +import { EventVolunteer, EventVolunteerGroup } from "../../../src/models"; +import { getEventVolunteerGroups } from "../../../src/resolvers/Query/getEventVolunteerGroups"; +import type { TestOrganizationType } from "../../helpers/userAndOrg"; let MONGOOSE_INSTANCE: typeof mongoose; +let testOrganization: TestOrganizationType; let testEvent: TestEventType; -let testEventVolunteerGroup: TestEventVolunteerGroupType; +let testUser1: TestUserType; +let testEventVolunteer1: TestEventVolunteerType; +let testVolunteerGroup1: TestEventVolunteerGroupType; +let testVolunteerGroup2: TestEventVolunteerGroupType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - const temp = await createTestEventVolunteerGroup(); - testEvent = temp[2]; - testEventVolunteerGroup = temp[4]; + const [organization, event, user1, , volunteer1, , volunteerGroup] = + await createVolunteerAndActions(); + + testOrganization = organization; + testEvent = event; + testUser1 = user1; + testEventVolunteer1 = volunteer1; + testVolunteerGroup1 = volunteerGroup; + testVolunteerGroup2 = await EventVolunteerGroup.create({ + creator: testUser1?._id, + event: testEvent?._id, + volunteers: [testEventVolunteer1?._id], + leader: testUser1?._id, + assignments: [], + name: "Test Volunteer Group 2", + }); + + await EventVolunteer.updateOne( + { _id: testEventVolunteer1?._id }, + { groups: [testVolunteerGroup1?._id, testVolunteerGroup2?._id] }, + { + new: true, + }, + ); }); afterAll(async () => { @@ -25,31 +54,77 @@ afterAll(async () => { }); describe("resolvers -> Query -> getEventVolunteerGroups", () => { - it(`returns list of all existing event volunteer groups with eventId === args.where.eventId`, async () => { - const volunteerGroupsPayload = (await getEventVolunteerGroups?.( + it(`getEventVolunteerGroups - eventId, name_contains, orderBy is volunteers_ASC`, async () => { + const groups = (await getEventVolunteerGroups?.( {}, { where: { eventId: testEvent?._id, + name_contains: testVolunteerGroup1.name, + leaderName: testUser1?.firstName, }, + orderBy: "volunteers_ASC", }, {}, - )) as unknown as EventVolunteerGroup[]; + )) as unknown as InterfaceEventVolunteerGroup[]; + + expect(groups[0].name).toEqual(testVolunteerGroup1.name); + }); + + it(`getEventVolunteerGroups - userId, orgId, orderBy is volunteers_DESC`, async () => { + const groups = (await getEventVolunteerGroups?.( + {}, + { + where: { + userId: testUser1?._id.toString(), + orgId: testOrganization?._id, + }, + orderBy: "volunteers_DESC", + }, + {}, + )) as unknown as InterfaceEventVolunteerGroup[]; + expect(groups.length).toEqual(2); + }); - expect(volunteerGroupsPayload[0]._id).toEqual(testEventVolunteerGroup._id); + it(`getEventVolunteerGroups - eventId, orderBy is assignments_ASC`, async () => { + const groups = (await getEventVolunteerGroups?.( + {}, + { + where: { + eventId: testEvent?._id, + }, + orderBy: "assignments_ASC", + }, + {}, + )) as unknown as InterfaceEventVolunteerGroup[]; + expect(groups[0].name).toEqual(testVolunteerGroup2.name); }); - it(`returns empty list of all existing event volunteer groups with eventId !== args.where.eventId`, async () => { - const volunteerGroupsPayload = (await getEventVolunteerGroups?.( + it(`getEventVolunteerGroups - eventId, orderBy is assignements_DESC`, async () => { + const groups = (await getEventVolunteerGroups?.( {}, { where: { - eventId: "123456789012345678901234", + eventId: testEvent?._id, }, + orderBy: "assignments_DESC", }, {}, - )) as unknown as EventVolunteerGroup[]; + )) as unknown as InterfaceEventVolunteerGroup[]; + expect(groups[0].name).toEqual(testVolunteerGroup1.name); + }); - expect(volunteerGroupsPayload).toEqual([]); + it(`getEventVolunteerGroups - userId, wrong orgId`, async () => { + const groups = (await getEventVolunteerGroups?.( + {}, + { + where: { + userId: testUser1?._id.toString(), + orgId: testEvent?._id, + }, + }, + {}, + )) as unknown as InterfaceEventVolunteerGroup[]; + expect(groups).toEqual([]); }); }); diff --git a/tests/resolvers/Query/getEventVolunteers.spec.ts b/tests/resolvers/Query/getEventVolunteers.spec.ts new file mode 100644 index 0000000000..93c532c0d3 --- /dev/null +++ b/tests/resolvers/Query/getEventVolunteers.spec.ts @@ -0,0 +1,62 @@ +import type mongoose from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { + TestEventType, + TestEventVolunteerGroupType, + TestEventVolunteerType, +} from "../../helpers/events"; +import type { TestUserType } from "../../helpers/user"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceEventVolunteer } from "../../../src/models"; +import { getEventVolunteers } from "../../../src/resolvers/Query/getEventVolunteers"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testEvent: TestEventType; +let testUser1: TestUserType; +let testEventVolunteer1: TestEventVolunteerType; +let testVolunteerGroup: TestEventVolunteerGroupType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const [, event, user1, , volunteer1, , volunteerGroup, ,] = + await createVolunteerAndActions(); + + testEvent = event; + testUser1 = user1; + testEventVolunteer1 = volunteer1; + testVolunteerGroup = volunteerGroup; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> getEventVolunteers", () => { + it(`getEventVolunteers - eventId, name_contains`, async () => { + const eventVolunteers = (await getEventVolunteers?.( + {}, + { + where: { + eventId: testEvent?._id, + name_contains: testUser1?.firstName, + }, + }, + {}, + )) as unknown as InterfaceEventVolunteer[]; + expect(eventVolunteers[0].user.firstName).toEqual(testUser1?.firstName); + }); + it(`getEventVolunteers - eventId, groupId`, async () => { + const eventVolunteers = (await getEventVolunteers?.( + {}, + { + where: { + eventId: testEvent?._id, + groupId: testVolunteerGroup?._id, + }, + }, + {}, + )) as unknown as InterfaceEventVolunteer[]; + expect(eventVolunteers[0]._id).toEqual(testEventVolunteer1?._id); + }); +}); diff --git a/tests/resolvers/Query/getFile.spec.ts b/tests/resolvers/Query/getFile.spec.ts new file mode 100644 index 0000000000..a6ff41d4f4 --- /dev/null +++ b/tests/resolvers/Query/getFile.spec.ts @@ -0,0 +1,138 @@ +import { describe, it, expect, vi, beforeEach } from "vitest"; +import type { GetObjectCommandOutput } from "@aws-sdk/client-s3"; +import { GetObjectCommand } from "@aws-sdk/client-s3"; +import type { Request, Response } from "express"; +import type { Readable } from "stream"; +import { s3Client } from "../../../src/config/minio"; +import { getFile } from "../../../src/REST/controllers/query"; +import type { SdkStreamMixin } from "@aws-sdk/types"; + +// Mock the s3Client +vi.mock("../../../src/config/minio", () => ({ + s3Client: { + send: vi.fn(), + }, + BUCKET_NAME: "test-bucket", +})); + +describe("getFile", () => { + let mockRequest: Request; + let mockResponse: Response; + + beforeEach(() => { + vi.clearAllMocks(); + + mockResponse = { + setHeader: vi.fn(), + status: vi.fn().mockReturnThis(), + send: vi.fn(), + pipe: vi.fn(), + } as unknown as Response; + + mockRequest = { + params: { + "0": "test-file.txt", + }, + } as unknown as Request; + }); + + const createMockStream = (): Readable & SdkStreamMixin => { + // Create a minimal mock that implements only what we need + const mockStream = { + pipe: vi.fn().mockReturnThis(), + on: vi.fn().mockReturnThis(), + once: vi.fn().mockReturnThis(), + emit: vi.fn().mockReturnThis(), + transformToByteArray: (): Promise => + Promise.resolve(new Uint8Array()), + transformToWebStream: (): ReadableStream => new ReadableStream(), + }; + + return mockStream as unknown as Readable & SdkStreamMixin; + }; + + it("should successfully retrieve and stream a file", async () => { + const mockStream = createMockStream(); + + const send = vi.fn().mockImplementation(() => + Promise.resolve({ + Body: mockStream, + ContentType: "text/plain", + $metadata: {}, + } as GetObjectCommandOutput), + ); + + vi.mocked(s3Client.send).mockImplementation(send); + + await getFile(mockRequest, mockResponse); + + expect(s3Client.send).toHaveBeenCalledWith(expect.any(GetObjectCommand)); + + const commandCall = vi.mocked(s3Client.send).mock + .calls[0][0] as GetObjectCommand; + expect(commandCall.input).toEqual({ + Bucket: "test-bucket", + Key: "test-file.txt", + }); + + expect(mockResponse.setHeader).toHaveBeenCalledWith( + "Content-Type", + "text/plain", + ); + expect(mockResponse.setHeader).toHaveBeenCalledWith( + "Cross-Origin-Resource-Policy", + "same-site", + ); + + expect(mockStream.pipe).toHaveBeenCalledWith(mockResponse); + }); + + it("should handle errors when retrieving file fails", async () => { + const mockError = new Error("Failed to retrieve file"); + const send = vi.fn().mockImplementation(() => Promise.reject(mockError)); + vi.mocked(s3Client.send).mockImplementation(send); + + const consoleErrorSpy = vi.spyOn(console, "error"); + + await getFile(mockRequest, mockResponse); + + expect(consoleErrorSpy).toHaveBeenCalledWith( + "Error fetching file:", + mockError, + ); + + expect(mockResponse.status).toHaveBeenCalledWith(500); + expect(mockResponse.send).toHaveBeenCalledWith( + "Error occurred while fetching file", + ); + }); + + it("should handle file paths with subdirectories", async () => { + const mockRequestWithPath = { + params: { + "0": "subfolder/nested/test-file.txt", + }, + } as unknown as Request; + + const mockStream = createMockStream(); + + const send = vi.fn().mockImplementation(() => + Promise.resolve({ + Body: mockStream, + ContentType: "text/plain", + $metadata: {}, + } as GetObjectCommandOutput), + ); + + vi.mocked(s3Client.send).mockImplementation(send); + + await getFile(mockRequestWithPath, mockResponse); + + const commandCall = vi.mocked(s3Client.send).mock + .calls[0][0] as GetObjectCommand; + expect(commandCall.input).toEqual({ + Bucket: "test-bucket", + Key: "subfolder/nested/test-file.txt", + }); + }); +}); diff --git a/tests/resolvers/Query/getRecurringEvents.spec.ts b/tests/resolvers/Query/getRecurringEvents.spec.ts new file mode 100644 index 0000000000..8b995ca4b3 --- /dev/null +++ b/tests/resolvers/Query/getRecurringEvents.spec.ts @@ -0,0 +1,118 @@ +import "dotenv/config"; +import { getRecurringEvents } from "../../../src/resolvers/Query/getRecurringEvents"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { Event } from "../../../src/models"; +import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; +import { Types } from "mongoose"; +import { + createTestUser, + createTestUserAndOrganization, + type TestOrganizationType, + type TestUserType, +} from "../../helpers/userAndOrg"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testUser: TestUserType; +let testAdminUser: TestUserType; +let testOrganization: TestOrganizationType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const result = await createTestUserAndOrganization(); + testUser = result[0]; + testOrganization = result[1]; + testAdminUser = await createTestUser(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> getRecurringEvents", () => { + it("returns list of recurring events for a given baseRecurringEventId", async () => { + if (!testUser || !testAdminUser || !testOrganization) { + throw new Error("Test setup failed"); + } + const baseRecurringEventId = new Types.ObjectId(); + + const testEvents = [ + { + title: "Event 1", + description: "description", + allDay: true, + startDate: new Date().toUTCString(), + recurring: true, + isPublic: true, + isRegisterable: true, + creatorId: testUser._id, + admins: [testAdminUser._id], + registrants: [], + organization: testOrganization._id, + baseRecurringEventId, + }, + { + title: "Event 2", + description: "description", + allDay: true, + startDate: new Date(), + recurring: true, + isPublic: true, + isRegisterable: true, + creatorId: testUser._id, + admins: [testAdminUser._id], + registrants: [], + organization: testOrganization._id, + baseRecurringEventId, + }, + ]; + + await Event.insertMany(testEvents); + + const args = { baseRecurringEventId: baseRecurringEventId.toString() }; + const getRecurringEventsFunction = getRecurringEvents as unknown as ( + parent: any, + args: any, + context: any, + ) => Promise; + const result = await getRecurringEventsFunction({}, args, {}); + + expect(result).toHaveLength(2); + expect(result[0].title).toBe("Event 1"); + expect(result[1].title).toBe("Event 2"); + + await Event.deleteMany({ baseRecurringEventId }); + }); + + it("returns an empty array when no recurring events are found", async () => { + const nonExistentId = new Types.ObjectId(); + const args = { baseRecurringEventId: nonExistentId.toString() }; + const getRecurringEventsFunction = getRecurringEvents as unknown as ( + parent: any, + args: any, + context: any, + ) => Promise; + const result = await getRecurringEventsFunction({}, args, {}); + + expect(result).toEqual([]); + }); + + it("throws an error when there's a problem fetching events", async () => { + const mockFind = vi.spyOn(Event, "find").mockImplementation(() => { + throw new Error("Database error"); + }); + + const args = { baseRecurringEventId: new Types.ObjectId().toString() }; + const getRecurringEventsFunction = getRecurringEvents as unknown as ( + parent: any, + args: any, + context: any, + ) => Promise; + + await expect(getRecurringEventsFunction({}, args, {})).rejects.toThrow( + "Database error", + ); + + mockFind.mockRestore(); + }); +}); diff --git a/tests/resolvers/Query/getUserTag.spec.ts b/tests/resolvers/Query/getUserTag.spec.ts index f81f51d960..0e935a383a 100644 --- a/tests/resolvers/Query/getUserTag.spec.ts +++ b/tests/resolvers/Query/getUserTag.spec.ts @@ -22,7 +22,7 @@ afterAll(async () => { await disconnect(MONGOOSE_INSTANCE); }); -describe("resolvers -> Query -> getUserTagAncestors", () => { +describe("resolvers -> Query -> getUserTag", () => { it(`throws NotFoundError if no userTag exists with _id === args.id`, async () => { const { requestContext } = await import("../../../src/libraries"); @@ -49,8 +49,8 @@ describe("resolvers -> Query -> getUserTagAncestors", () => { id: testTag?._id.toString() ?? "", }; - const getUserTagAncestorsPayload = await getUserTagResolver?.({}, args, {}); + const getUserTagPayload = await getUserTagResolver?.({}, args, {}); - expect(getUserTagAncestorsPayload).toEqual(testTag); + expect(getUserTagPayload).toEqual(testTag); }); }); diff --git a/tests/resolvers/Query/getUserTagAncestors.spec.ts b/tests/resolvers/Query/getUserTagAncestors.spec.ts deleted file mode 100644 index 2a3ee00143..0000000000 --- a/tests/resolvers/Query/getUserTagAncestors.spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { getUserTagAncestors as getUserTagAncestorsResolver } from "../../../src/resolvers/Query/getUserTagAncestors"; -import type { QueryGetUserTagAncestorsArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect, vi } from "vitest"; -import { - createTwoLevelTagsWithOrg, - type TestUserTagType, -} from "../../helpers/tags"; -import { TAG_NOT_FOUND } from "../../../src/constants"; - -let MONGOOSE_INSTANCE: typeof mongoose; - -let testTag: TestUserTagType; -let testSubTag1: TestUserTagType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - [, , [testTag, testSubTag1]] = await createTwoLevelTagsWithOrg(); -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> getUserTagAncestors", () => { - it(`throws NotFoundError if no userTag exists with _id === args.id`, async () => { - const { requestContext } = await import("../../../src/libraries"); - - const spy = vi - .spyOn(requestContext, "translate") - .mockImplementationOnce((message) => `Translated ${message}`); - - try { - const args: QueryGetUserTagAncestorsArgs = { - id: new Types.ObjectId().toString(), - }; - - await getUserTagAncestorsResolver?.({}, args, {}); - } catch (error: unknown) { - expect(spy).toHaveBeenLastCalledWith(TAG_NOT_FOUND.MESSAGE); - expect((error as Error).message).toEqual( - `Translated ${TAG_NOT_FOUND.MESSAGE}`, - ); - } - }); - - it(`returns the list of all the ancestor tags for a tag with _id === args.id`, async () => { - const args: QueryGetUserTagAncestorsArgs = { - id: testSubTag1?._id.toString() ?? "", - }; - - const getUserTagAncestorsPayload = await getUserTagAncestorsResolver?.( - {}, - args, - {}, - ); - - expect(getUserTagAncestorsPayload).toEqual([testTag, testSubTag1]); - }); -}); diff --git a/tests/resolvers/Query/getVolunteerMembership.spec.ts b/tests/resolvers/Query/getVolunteerMembership.spec.ts new file mode 100644 index 0000000000..ecc68c5d3a --- /dev/null +++ b/tests/resolvers/Query/getVolunteerMembership.spec.ts @@ -0,0 +1,170 @@ +import type mongoose from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { + TestEventType, + TestEventVolunteerGroupType, + TestEventVolunteerType, +} from "../../helpers/events"; +import type { TestUserType } from "../../helpers/user"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import type { InterfaceVolunteerMembership } from "../../../src/models"; +import { VolunteerMembership } from "../../../src/models"; +import { getVolunteerMembership } from "../../../src/resolvers/Query/getVolunteerMembership"; + +export enum MembershipStatus { + INVITED = "invited", + REQUESTED = "requested", + ACCEPTED = "accepted", + REJECTED = "rejected", +} + +let MONGOOSE_INSTANCE: typeof mongoose; +let testEvent: TestEventType; +let testUser1: TestUserType; +let testEventVolunteer1: TestEventVolunteerType; +let testEventVolunteerGroup: TestEventVolunteerGroupType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const [, event, user1, , volunteer1, , volunteerGroup, ,] = + await createVolunteerAndActions(); + + testEvent = event; + testUser1 = user1; + testEventVolunteer1 = volunteer1; + testEventVolunteerGroup = volunteerGroup; + + await VolunteerMembership.insertMany([ + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.INVITED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + group: testEventVolunteerGroup._id, + status: MembershipStatus.REQUESTED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.ACCEPTED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.REJECTED, + }, + { + event: testEvent?._id, + volunteer: testEventVolunteer1._id, + status: MembershipStatus.INVITED, + group: testEventVolunteerGroup._id, + }, + ]); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> getVolunteerMembership", () => { + it(`getVolunteerMembership for userId, status invited`, async () => { + const volunteerMemberships = (await getVolunteerMembership?.( + {}, + { + where: { + userId: testUser1?._id.toString(), + status: MembershipStatus.INVITED, + }, + }, + {}, + )) as unknown as InterfaceVolunteerMembership[]; + expect(volunteerMemberships[0].volunteer?._id).toEqual( + testEventVolunteer1?._id, + ); + expect(volunteerMemberships[0].status).toEqual(MembershipStatus.INVITED); + }); + + it(`getVolunteerMembership for eventId, status accepted`, async () => { + const volunteerMemberships = (await getVolunteerMembership?.( + {}, + { + where: { + eventId: testEvent?._id, + eventTitle: testEvent?.title, + status: MembershipStatus.ACCEPTED, + }, + orderBy: "createdAt_ASC", + }, + {}, + )) as unknown as InterfaceVolunteerMembership[]; + expect(volunteerMemberships[0].volunteer?._id).toEqual( + testEventVolunteer1?._id, + ); + expect(volunteerMemberships[0].status).toEqual(MembershipStatus.ACCEPTED); + expect(volunteerMemberships[0].event._id).toEqual(testEvent?._id); + }); + + it(`getVolunteerMembership for eventId, filter group, userName`, async () => { + const volunteerMemberships = (await getVolunteerMembership?.( + {}, + { + where: { + eventId: testEvent?._id, + filter: "group", + userName: testUser1?.firstName, + }, + }, + {}, + )) as unknown as InterfaceVolunteerMembership[]; + expect(volunteerMemberships[0].volunteer?._id).toEqual( + testEventVolunteer1?._id, + ); + expect(volunteerMemberships[0].status).toEqual(MembershipStatus.REQUESTED); + expect(volunteerMemberships[0].event._id).toEqual(testEvent?._id); + expect(volunteerMemberships[0].group?._id).toEqual( + testEventVolunteerGroup?._id, + ); + }); + + it(`getVolunteerMembership for userId`, async () => { + const volunteerMemberships = (await getVolunteerMembership?.( + {}, + { + where: { + userId: testUser1?._id.toString(), + filter: "individual", + }, + }, + {}, + )) as unknown as InterfaceVolunteerMembership[]; + expect(volunteerMemberships.length).toEqual(3); + expect(volunteerMemberships[0].group).toBeUndefined(); + expect(volunteerMemberships[1].group).toBeUndefined(); + expect(volunteerMemberships[2].group).toBeUndefined(); + }); + + it(`getVolunteerMembership for eventId, groupId`, async () => { + const volunteerMemberships = (await getVolunteerMembership?.( + {}, + { + where: { + eventId: testEvent?._id, + groupId: testEventVolunteerGroup?._id, + filter: "group", + userName: testUser1?.firstName, + }, + }, + {}, + )) as unknown as InterfaceVolunteerMembership[]; + expect(volunteerMemberships[0].volunteer?._id).toEqual( + testEventVolunteer1?._id, + ); + expect(volunteerMemberships[0].group?._id).toEqual( + testEventVolunteerGroup?._id, + ); + }); +}); diff --git a/tests/resolvers/Query/getVolunteerRanks.spec.ts b/tests/resolvers/Query/getVolunteerRanks.spec.ts new file mode 100644 index 0000000000..0f5d6973d5 --- /dev/null +++ b/tests/resolvers/Query/getVolunteerRanks.spec.ts @@ -0,0 +1,100 @@ +import type mongoose from "mongoose"; +import { connect, disconnect } from "../../helpers/db"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { VolunteerRank } from "../../../src/types/generatedGraphQLTypes"; +import type { TestUserType } from "../../helpers/user"; +import type { TestOrganizationType } from "../../helpers/userAndOrg"; +import { createVolunteerAndActions } from "../../helpers/volunteers"; +import { getVolunteerRanks } from "../../../src/resolvers/Query/getVolunteerRanks"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testOrganization: TestOrganizationType; +let testUser1: TestUserType; +let testUser2: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const [organization, , user1, user2] = await createVolunteerAndActions(); + testOrganization = organization; + testUser1 = user1; + testUser2 = user2; +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Query -> getVolunteerRanks", () => { + it(`getVolunteerRanks for allTime, descending, no limit/name`, async () => { + const volunteerRanks = (await getVolunteerRanks?.( + {}, + { + orgId: testOrganization?._id, + where: { + timeFrame: "allTime", + orderBy: "hours_DESC", + }, + }, + {}, + )) as unknown as VolunteerRank[]; + expect(volunteerRanks[0].hoursVolunteered).toEqual(10); + expect(volunteerRanks[0].user._id).toEqual(testUser1?._id); + expect(volunteerRanks[0].rank).toEqual(1); + expect(volunteerRanks[1].hoursVolunteered).toEqual(8); + expect(volunteerRanks[1].user._id).toEqual(testUser2?._id); + expect(volunteerRanks[1].rank).toEqual(2); + }); + + it(`getVolunteerRanks for weekly, descending, limit, no name`, async () => { + const volunteerRanks = (await getVolunteerRanks?.( + {}, + { + orgId: testOrganization?._id, + where: { + timeFrame: "weekly", + orderBy: "hours_DESC", + limit: 1, + }, + }, + {}, + )) as unknown as VolunteerRank[]; + expect(volunteerRanks[0].hoursVolunteered).toEqual(2); + expect(volunteerRanks[0].user._id).toEqual(testUser1?._id); + expect(volunteerRanks[0].rank).toEqual(1); + }); + + it(`getVolunteerRanks for monthly, descending, name, no limit`, async () => { + const volunteerRanks = (await getVolunteerRanks?.( + {}, + { + orgId: testOrganization?._id, + where: { + timeFrame: "monthly", + orderBy: "hours_ASC", + nameContains: testUser1?.firstName, + }, + }, + {}, + )) as unknown as VolunteerRank[]; + expect(volunteerRanks[0].hoursVolunteered).toEqual(2); + expect(volunteerRanks[0].user._id).toEqual(testUser1?._id); + expect(volunteerRanks[0].rank).toEqual(1); + }); + + it(`getVolunteerRanks for yearly, descending, no name/limit`, async () => { + const volunteerRanks = (await getVolunteerRanks?.( + {}, + { + orgId: testOrganization?._id, + where: { + timeFrame: "yearly", + orderBy: "hours_DESC", + }, + }, + {}, + )) as unknown as VolunteerRank[]; + expect(volunteerRanks[0].hoursVolunteered).toEqual(8); + expect(volunteerRanks[0].user._id).toEqual(testUser1?._id); + expect(volunteerRanks[0].rank).toEqual(1); + }); +}); diff --git a/tests/resolvers/Query/groupChatById.spec.ts b/tests/resolvers/Query/groupChatById.spec.ts deleted file mode 100644 index 2440387c61..0000000000 --- a/tests/resolvers/Query/groupChatById.spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { groupChatById as groupChatByIdResolver } from "../../../src/resolvers/Query/groupChatById"; -import { GroupChat } from "../../../src/models"; -import type { - QueryGroupChatByIdArgs, - QueryGroupChatsByUserIdArgs, -} from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { TestGroupChatType } from "../../helpers/groupChat"; - -let testGroupChat: TestGroupChatType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testGroupChat = resultArray[2]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> directChatsById", () => { - it(`throws NotFoundError if no directChats exists with directChats._id === args.id`, async () => { - try { - const args: QueryGroupChatByIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await groupChatByIdResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("Chat not found"); - } - }); - - it(`returns list of all directChats with directChat.users containing the user - with _id === args.id`, async () => { - const args: QueryGroupChatsByUserIdArgs = { - id: testGroupChat?._id.toString() ?? "defaultString", - }; - - const directChatsByUserIdPayload = await groupChatByIdResolver?.( - {}, - args, - {}, - ); - - const directChatsByUserId = await GroupChat.findById( - testGroupChat?._id, - ).lean(); - console.log(directChatsByUserIdPayload); - console.log(directChatsByUserId); - expect(directChatsByUserIdPayload).toEqual(directChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/groupChatsByUserId.spec.ts b/tests/resolvers/Query/groupChatsByUserId.spec.ts deleted file mode 100644 index 7026580b17..0000000000 --- a/tests/resolvers/Query/groupChatsByUserId.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import "dotenv/config"; -import type mongoose from "mongoose"; -import { Types } from "mongoose"; -import { connect, disconnect } from "../../helpers/db"; - -import { groupChatsByUserId as groupChatsByUserIdResolver } from "../../../src/resolvers/Query/groupChatsByUserId"; -import { GroupChat } from "../../../src/models"; -import type { QueryGroupChatsByUserIdArgs } from "../../../src/types/generatedGraphQLTypes"; -import { beforeAll, afterAll, describe, it, expect } from "vitest"; -import { createTestGroupChat } from "../../helpers/groupChat"; -import type { TestUserType } from "../../helpers/userAndOrg"; - -let testUser: TestUserType; -let MONGOOSE_INSTANCE: typeof mongoose; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestGroupChat(); - testUser = resultArray[0]; -}); - -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("resolvers -> Query -> groupChatsByUserId", () => { - it(`throws NotFoundError if no groupChats exists with groupChats.users - containing user with _id === args.id`, async () => { - try { - const args: QueryGroupChatsByUserIdArgs = { - id: new Types.ObjectId().toString(), - }; - - await groupChatsByUserIdResolver?.({}, args, {}); - } catch (error: unknown) { - expect((error as Error).message).toEqual("Group Chats not found"); - } - }); - - it(`returns list of all groupChats with groupChat.users containing the user - with _id === args.id`, async () => { - const args: QueryGroupChatsByUserIdArgs = { - id: testUser?._id, - }; - - const groupChatsByUserIdPayload = await groupChatsByUserIdResolver?.( - {}, - args, - {}, - ); - - const groupChatsByUserId = await GroupChat.find({ - users: testUser?._id, - }).lean(); - - expect(groupChatsByUserIdPayload).toEqual(groupChatsByUserId); - }); -}); diff --git a/tests/resolvers/Query/helperFunctions/getSort.spec.ts b/tests/resolvers/Query/helperFunctions/getSort.spec.ts index 10b0b1668c..98c5ca9434 100644 --- a/tests/resolvers/Query/helperFunctions/getSort.spec.ts +++ b/tests/resolvers/Query/helperFunctions/getSort.spec.ts @@ -9,6 +9,9 @@ import type { VenueOrderByInput, FundOrderByInput, CampaignOrderByInput, + ActionItemsOrderByInput, + EventVolunteersOrderByInput, + VolunteerMembershipOrderByInput, } from "../../../../src/types/generatedGraphQLTypes"; describe("getSort function", () => { @@ -61,6 +64,8 @@ describe("getSort function", () => { ["fundingGoal_DESC", { fundingGoal: -1 }], ["dueDate_ASC", { dueDate: 1 }], ["dueDate_DESC", { dueDate: -1 }], + ["hoursVolunteered_ASC", { hoursVolunteered: 1 }], + ["hoursVolunteered_DESC", { hoursVolunteered: -1 }], ]; it.each(testCases)( @@ -75,7 +80,10 @@ describe("getSort function", () => { | VenueOrderByInput | PledgeOrderByInput | FundOrderByInput - | CampaignOrderByInput, + | CampaignOrderByInput + | ActionItemsOrderByInput + | EventVolunteersOrderByInput + | VolunteerMembershipOrderByInput, ); expect(result).toEqual(expected); }, diff --git a/tests/resolvers/Query/helperFunctions/getWhere.spec.ts b/tests/resolvers/Query/helperFunctions/getWhere.spec.ts index 3c3494c9b6..b6e8c12faa 100644 --- a/tests/resolvers/Query/helperFunctions/getWhere.spec.ts +++ b/tests/resolvers/Query/helperFunctions/getWhere.spec.ts @@ -13,6 +13,7 @@ import type { EventVolunteerGroupWhereInput, PledgeWhereInput, ActionItemCategoryWhereInput, + EventVolunteerWhereInput, } from "../../../../src/types/generatedGraphQLTypes"; describe("getWhere function", () => { @@ -30,7 +31,8 @@ describe("getWhere function", () => { FundWhereInput & CampaignWhereInput & VenueWhereInput & - PledgeWhereInput + PledgeWhereInput & + EventVolunteerWhereInput >, Record, ][] = [ @@ -335,17 +337,10 @@ describe("getWhere function", () => { { organizationId: "6f6cd" }, ], ["campaignId", { campaignId: "6f6c" }, { _id: "6f6c" }], - [ - "volunteerId", - { volunteerId: "6f43d" }, - { - volunteers: { - $in: ["6f43d"], - }, - }, - ], ["is_disabled", { is_disabled: true }, { isDisabled: true }], ["is_disabled", { is_disabled: false }, { isDisabled: false }], + ["hasAccepted", { hasAccepted: true }, { hasAccepted: true }], + ["hasAccepted", { hasAccepted: false }, { hasAccepted: false }], ]; it.each(testCases)( diff --git a/tests/resolvers/Query/organizationsMemberConnection.spec.ts b/tests/resolvers/Query/organizationsMemberConnection.spec.ts index 0a773fcda5..9265454acf 100644 --- a/tests/resolvers/Query/organizationsMemberConnection.spec.ts +++ b/tests/resolvers/Query/organizationsMemberConnection.spec.ts @@ -248,6 +248,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -341,6 +342,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); // console.log(organizationsMemberConnectionPayload, usersWithPassword); @@ -433,6 +435,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -528,6 +531,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -623,6 +627,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -706,6 +711,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -888,6 +894,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -960,6 +967,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -1061,6 +1069,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); @@ -1085,7 +1094,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { {}, { $set: { - image: `image/image.png`, + image: BASE_URL + `image/image.png`, }, }, ); @@ -1132,7 +1141,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { employmentStatus: user.employmentStatus, firstName: user.firstName, gender: user.gender, - image: `${BASE_URL}${user.image}`, + image: user.image, joinedOrganizations: user.joinedOrganizations, lastName: user.lastName, maritalStatus: user.maritalStatus, @@ -1143,6 +1152,7 @@ describe("resolvers -> Query -> organizationsMemberConnection", () => { registeredEvents: user.registeredEvents, status: user.status, updatedAt: user.updatedAt, + eventsAttended: user.eventsAttended, }; }); diff --git a/tests/resolvers/Query/post.spec.ts b/tests/resolvers/Query/post.spec.ts index 7d6c1afe9e..4f89104ec3 100644 --- a/tests/resolvers/Query/post.spec.ts +++ b/tests/resolvers/Query/post.spec.ts @@ -51,14 +51,9 @@ describe("resolvers -> Query -> post", () => { const post = await Post.findOne({ _id: testPost?._id }) .populate("organization") - .populate("likedBy") + .populate(["likedBy", "file"]) .lean(); - if (post) { - post.imageUrl = `${context.apiRootUrl}${post.imageUrl}`; - post.videoUrl = `${context.apiRootUrl}${post.videoUrl}`; - } - expect(postPayload).toEqual(post); }); it(`returns post object with null image and video links`, async () => { @@ -74,14 +69,9 @@ describe("resolvers -> Query -> post", () => { const post = await Post.findOne({ _id: testPost?._id }) .populate("organization") - .populate("likedBy") + .populate(["likedBy", "file"]) .lean(); - if (post) { - post.imageUrl = null; - post.videoUrl = null; - } - expect(postPayload).toEqual(post); }); }); diff --git a/tests/resolvers/Query/user.spec.ts b/tests/resolvers/Query/user.spec.ts index 3d00aebbc6..23f2c090cc 100644 --- a/tests/resolvers/Query/user.spec.ts +++ b/tests/resolvers/Query/user.spec.ts @@ -1,7 +1,7 @@ import "dotenv/config"; import type mongoose from "mongoose"; import { Types } from "mongoose"; -import { BASE_URL, USER_NOT_FOUND_ERROR } from "../../../src/constants"; +import { USER_NOT_FOUND_ERROR } from "../../../src/constants"; import { User } from "../../../src/models"; import { user as userResolver } from "../../../src/resolvers/Query/user"; import { connect, disconnect } from "../../helpers/db"; @@ -64,37 +64,4 @@ describe("resolvers -> Query -> user", () => { image: null, }); }); - it(`returns user object with image`, async () => { - await User.findOneAndUpdate( - { - _id: testUser?.id, - }, - { - $set: { - image: `images/newImage.png`, - }, - }, - ); - - const args: QueryUserArgs = { - id: testUser?.id, - }; - - const context = { - userId: testUser?.id, - apiRootUrl: BASE_URL, - }; - - const userPayload = await userResolver?.({}, args, context); - - const user = await User.findOne({ - _id: testUser?._id, - }).lean(); - - expect(userPayload?.user).toEqual({ - ...user, - organizationsBlockedBy: [], - image: user?.image ? `${BASE_URL}${user.image}` : null, - }); - }); }); diff --git a/tests/resolvers/Subscription/directMessageChat.spec.ts b/tests/resolvers/Subscription/directMessageChat.spec.ts deleted file mode 100644 index 599ad5e937..0000000000 --- a/tests/resolvers/Subscription/directMessageChat.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import "dotenv/config"; -import { describe, it, expect } from "vitest"; - -describe("src -> resolvers -> Subscription -> directMessageChat", () => { - it("should return payload", async () => { - const { directMessageChat: directMessageChatPayload } = await import( - "../../../src/resolvers/Subscription/directMessageChat" - ); - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (chatChannel: string): string => { - return chatChannel; - }, - }, - }; - // @ts-expect-error-ignore - const x = directMessageChatPayload?.subscribe(_parent, _args, context); - expect(x).not.toBe(null); - }); -}); diff --git a/tests/resolvers/Subscription/messageSentToChat.spec.ts b/tests/resolvers/Subscription/messageSentToChat.spec.ts new file mode 100644 index 0000000000..768b0f5c47 --- /dev/null +++ b/tests/resolvers/Subscription/messageSentToChat.spec.ts @@ -0,0 +1,88 @@ +import "dotenv/config"; +import { describe, it, expect, beforeAll, afterAll } from "vitest"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import type { TestChatMessageType } from "../../helpers/chat"; +import { createTestChatMessage } from "../../helpers/chat"; +import type { TestUserType } from "../../helpers/userAndOrg"; +import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToChat"; +import { Types } from "mongoose"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testChatMessage: TestChatMessageType; +let testCurrentUser: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + const resultArray = await createTestChatMessage(); + testCurrentUser = resultArray[0]; + testChatMessage = resultArray[3]; +}); +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("src -> resolvers -> Subscription -> messageSentToChat", () => { + it("subscription filter function returns true if CurrentUser is receiveror sender", async () => { + const { messageSentToChat: messageSentToChatPayload } = await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); + + const _args = {}; + const _parent = {}; + const context = { + pubsub: { + asyncIterator: (_action: "MESSAGE_SENT_TO_CHAT"): string => { + return _action; + }, + }, + context: { currentUserId: testCurrentUser?._id }, + }; + const variables = { + userId: testCurrentUser?._id, + }; + const payload = { + messageSentToChat: { + chatMessageBelongsTo: testChatMessage?.chatMessageBelongsTo as string, + }, + }; + // @ts-expect-error-ignore + messageSentToChatPayload.payload = payload; + // @ts-expect-error-ignore + const x = messageSentToChatPayload?.subscribe(_parent, _args, context); + expect(x).not.toBe(null); + expect(await filterFunction(payload, variables)).toBe(true); + }); + + it("user is not notified if it is not a part of chat", async () => { + const { messageSentToChat: messageSentToChatPayload } = await import( + "../../../src/resolvers/Subscription/messageSentToChat" + ); + + const _args = {}; + const _parent = {}; + const context = { + pubsub: { + asyncIterator: (_action: "MESSAGE_SENT_TO_CHAT"): string => { + return _action; + }, + }, + context: { currentUserId: testCurrentUser?._id }, + }; + const variables = { + userId: testCurrentUser?._id, + }; + + const payload = { + messageSentToChat: { + chatMessageBelongsTo: new Types.ObjectId().toString(), + }, + }; + // @ts-expect-error-ignore + messageSentToChatPayload.payload = payload; + // @ts-expect-error-ignore + const x = messageSentToChatPayload?.subscribe(_parent, _args, context); + expect(x).not.toBe(null); + expect(await filterFunction(payload, variables)).toBe(false); + }); +}); diff --git a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts b/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts deleted file mode 100644 index 8a6fdff245..0000000000 --- a/tests/resolvers/Subscription/messageSentToDirectChat.spec.ts +++ /dev/null @@ -1,103 +0,0 @@ -import "dotenv/config"; -import { describe, it, expect, beforeAll, afterAll } from "vitest"; -import { connect, disconnect } from "../../helpers/db"; -import type mongoose from "mongoose"; -import type { TestDirectChatMessageType } from "../../helpers/directChat"; -import { createTestDirectChatMessage } from "../../helpers/directChat"; -import type { TestUserType } from "../../helpers/userAndOrg"; -import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToDirectChat"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testDirectChatMessage: TestDirectChatMessageType; -let testCurrentUser: TestUserType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - const resultArray = await createTestDirectChatMessage(); - testCurrentUser = resultArray[0]; - testDirectChatMessage = resultArray[3]; -}); -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("src -> resolvers -> Subscription -> messageSentToDirectChat", () => { - it("subscription filter function returns true if CurrentUser is receiveror sender", async () => { - const { messageSentToDirectChat: messageSentToDirectChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToDirectChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_DIRECT_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testCurrentUser?._id }, - }; - const variables = { - userId: testCurrentUser?._id, - }; - const payload = { - messageSentToDirectChat: { - receiver: testDirectChatMessage?.receiver, - sender: testDirectChatMessage?.sender, - }, - }; - // @ts-expect-error-ignore - messageSentToDirectChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToDirectChatPayload?.subscribe( - _parent, - _args, - context, - ); - expect(x).not.toBe(null); - expect(await filterFunction(payload, variables)).toBe(true); - - // If current User is sender - payload.messageSentToDirectChat.receiver = "receiver"; - expect(await filterFunction(payload, variables)).toBe(true); - }); - - it("user is not notified if it is not a part of DirectChat", async () => { - const { messageSentToDirectChat: messageSentToDirectChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToDirectChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_DIRECT_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testCurrentUser?._id }, - }; - const variables = { - userId: testCurrentUser?._id, - }; - - const payload = { - messageSentToDirectChat: { - receiver: "Receiver", - sender: "Sender", - }, - }; - // @ts-expect-error-ignore - messageSentToDirectChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToDirectChatPayload?.subscribe( - _parent, - _args, - context, - ); - expect(x).not.toBe(null); - expect(await filterFunction(payload, variables)).toBe(false); - }); -}); diff --git a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts b/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts deleted file mode 100644 index c1aa13072a..0000000000 --- a/tests/resolvers/Subscription/messageSentToGroupChat.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -import "dotenv/config"; -import { describe, it, expect, beforeAll, afterAll } from "vitest"; -import { connect, disconnect } from "../../helpers/db"; -import mongoose from "mongoose"; -import type { TestGroupChatType } from "../../helpers/groupChat"; -import { createTestGroupChatMessage } from "../../helpers/groupChat"; -import { filterFunction } from "../../../src/resolvers/Subscription/messageSentToGroupChat"; - -let MONGOOSE_INSTANCE: typeof mongoose; -let testGroupChat: TestGroupChatType; - -beforeAll(async () => { - MONGOOSE_INSTANCE = await connect(); - testGroupChat = (await createTestGroupChatMessage())[2]; -}); -afterAll(async () => { - await disconnect(MONGOOSE_INSTANCE); -}); - -describe("src -> resolvers -> Subscription -> messageSentToGroupChat", () => { - it("subscription filter function returns true", async () => { - const { messageSentToGroupChat: messageSentToGroupChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToGroupChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_GROUP_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testGroupChat?.users[0] }, - }; - const variables = { - userId: testGroupChat?.users[0], - }; - const payload = { - messageSentToGroupChat: { - groupChatMessageBelongsTo: testGroupChat?._id, - }, - }; - // @ts-expect-error-ignore - messageSentToGroupChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToGroupChatPayload?.subscribe(_parent, _args, context); - expect(x).not.toBe(null); - expect(await filterFunction(payload, variables)).toBe(true); - }); - it("subscription filter function returns false when group chat not found with the id", async () => { - const { messageSentToGroupChat: messageSentToGroupChatPayload } = - await import( - "../../../src/resolvers/Subscription/messageSentToGroupChat" - ); - - const _args = {}; - const _parent = {}; - const context = { - pubsub: { - asyncIterator: (_action: "MESSAGE_SENT_TO_GROUP_CHAT"): string => { - return _action; - }, - }, - context: { currentUserId: testGroupChat?.users[0] }, - }; - const payload = { - messageSentToGroupChat: { - groupChatMessageBelongsTo: new mongoose.Types.ObjectId(), - }, - }; - const variables = { - userId: testGroupChat?.users[0], - }; - // @ts-expect-error-ignore - messageSentToGroupChatPayload.payload = payload; - // @ts-expect-error-ignore - const x = messageSentToGroupChatPayload?.subscribe(_parent, _args, context); - expect(x).not.toBe(null); - expect(await filterFunction(payload, variables)).toBe(false); - }); -}); diff --git a/tests/resolvers/User/tagsAssignedWith.spec.ts b/tests/resolvers/User/tagsAssignedWith.spec.ts new file mode 100644 index 0000000000..6c8fd975dc --- /dev/null +++ b/tests/resolvers/User/tagsAssignedWith.spec.ts @@ -0,0 +1,128 @@ +import "dotenv/config"; +import { + parseCursor, + tagsAssignedWith as tagsAssignedWithResolver, +} from "../../../src/resolvers/User/tagsAssignedWith"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { TestUserTagType } from "../../helpers/tags"; +import type { + TestOrganizationType, + TestUserType, +} from "../../helpers/userAndOrg"; +import { createTagsAndAssignToUser } from "../../helpers/tags"; +import { GraphQLError } from "graphql"; +import type { DefaultGraphQLArgumentError } from "../../../src/utilities/graphQLConnection"; +import { + type InterfaceUser, + TagUser, + OrganizationTagUser, +} from "../../../src/models"; +import { Types } from "mongoose"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testTag: TestUserTagType, + testUser: TestUserType, + testOrganization: TestOrganizationType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [testUser, testOrganization, [testTag]] = await createTagsAndAssignToUser(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("tagsAssignedWith resolver", () => { + it(`throws GraphQLError if invalid arguments are provided to the resolver`, async () => { + const parent = testUser as InterfaceUser; + try { + await tagsAssignedWithResolver?.(parent, {}, {}); + } catch (error) { + if (error instanceof GraphQLError) { + expect(error.extensions.code).toEqual("INVALID_ARGUMENTS"); + expect( + (error.extensions.errors as DefaultGraphQLArgumentError[]).length, + ).toBeGreaterThan(0); + } + } + }); + + it(`returns the expected connection object`, async () => { + const parent = testUser as InterfaceUser; + const connection = await tagsAssignedWithResolver?.( + parent, + { + first: 3, + organizationId: testOrganization?._id, + }, + {}, + ); + + const tagUser = await TagUser.findOne({ + tagId: testTag?._id, + userId: testUser?._id, + }); + + const tag = await OrganizationTagUser.findOne({ + _id: testTag?._id, + }); + + const totalCount = await TagUser.find({ + userId: testUser?._id, + }).countDocuments(); + + expect(connection).toEqual({ + edges: [ + { + cursor: tagUser?._id.toString(), + node: tag?.toObject(), + }, + ], + pageInfo: { + endCursor: tagUser?._id.toString(), + hasNextPage: false, + hasPreviousPage: false, + startCursor: tagUser?._id.toString(), + }, + totalCount, + }); + }); +}); + +describe("parseCursor function", () => { + it("returns failure state if argument cursorValue is an invalid cursor", async () => { + const result = await parseCursor({ + cursorName: "after", + cursorPath: ["after"], + cursorValue: new Types.ObjectId().toString(), + userId: testUser?._id.toString() as string, + }); + + expect(result.isSuccessful).toEqual(false); + if (result.isSuccessful === false) { + expect(result.errors.length).toBeGreaterThan(0); + } + }); + + it("returns success state if argument cursorValue is a valid cursor", async () => { + const tagUser = await TagUser.findOne({ + tagId: testTag?._id, + userId: testUser?._id, + }); + + const result = await parseCursor({ + cursorName: "after", + cursorPath: ["after"], + cursorValue: tagUser?._id.toString() as string, + userId: testUser?._id.toString() as string, + }); + + expect(result.isSuccessful).toEqual(true); + if (result.isSuccessful === true) { + expect(result.parsedCursor).toEqual(tagUser?._id.toString()); + } + }); +}); diff --git a/tests/resolvers/UserTag/ancestorTags.spec.ts b/tests/resolvers/UserTag/ancestorTags.spec.ts new file mode 100644 index 0000000000..dd06ea5279 --- /dev/null +++ b/tests/resolvers/UserTag/ancestorTags.spec.ts @@ -0,0 +1,50 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { afterAll, beforeAll, describe, expect, it } from "vitest"; +import type { InterfaceOrganizationTagUser } from "../../../src/models"; +import { OrganizationTagUser } from "../../../src/models"; +import { ancestorTags as ancestorTagsResolver } from "../../../src/resolvers/UserTag/ancestorTags"; +import { connect, disconnect } from "../../helpers/db"; +import type { TestUserTagType } from "../../helpers/tags"; +import { createTwoLevelTagsWithOrg } from "../../helpers/tags"; +import type { TestOrganizationType } from "../../helpers/userAndOrg"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testRootTag: TestUserTagType, + testSubTagLevel1: TestUserTagType, + testSubTagLevel2: TestUserTagType; +let testOrganization: TestOrganizationType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [, testOrganization, [testRootTag, testSubTagLevel1]] = + await createTwoLevelTagsWithOrg(); + + testSubTagLevel2 = await OrganizationTagUser.create({ + name: "testSubTagLevel2", + parentTagId: testSubTagLevel1?._id, + organizationId: testOrganization?._id, + }); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("resolvers -> Tag -> ancestorTags", () => { + it(`returns an empty ancestorTags array for the root tag`, async () => { + const parent = testRootTag as InterfaceOrganizationTagUser; + + const payload = await ancestorTagsResolver?.(parent, {}, {}); + + expect(payload).toEqual([]); + }); + + it(`returns the correct ancestorTags array for a nested tag`, async () => { + const parent = testSubTagLevel2 as InterfaceOrganizationTagUser; + + const payload = await ancestorTagsResolver?.(parent, {}, {}); + + expect(payload).toEqual([testRootTag, testSubTagLevel1]); + }); +}); diff --git a/tests/resolvers/UserTag/childTags.spec.ts b/tests/resolvers/UserTag/childTags.spec.ts index 463dbb3e51..bb3aab877d 100644 --- a/tests/resolvers/UserTag/childTags.spec.ts +++ b/tests/resolvers/UserTag/childTags.spec.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import "dotenv/config"; import { GraphQLError } from "graphql"; import type mongoose from "mongoose"; diff --git a/tests/resolvers/UserTag/usersAssignedTo.spec.ts b/tests/resolvers/UserTag/usersAssignedTo.spec.ts index 52c52469ee..0333954353 100644 --- a/tests/resolvers/UserTag/usersAssignedTo.spec.ts +++ b/tests/resolvers/UserTag/usersAssignedTo.spec.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ import "dotenv/config"; import { parseCursor, @@ -8,7 +7,11 @@ import { connect, disconnect } from "../../helpers/db"; import type mongoose from "mongoose"; import { beforeAll, afterAll, describe, it, expect } from "vitest"; import type { TestUserTagType } from "../../helpers/tags"; -import type { TestUserType } from "../../helpers/userAndOrg"; +import type { + TestOrganizationType, + TestUserType, +} from "../../helpers/userAndOrg"; +import { createTestUser } from "../../helpers/userAndOrg"; import { createTagsAndAssignToUser } from "../../helpers/tags"; import { GraphQLError } from "graphql"; import type { DefaultGraphQLArgumentError } from "../../../src/utilities/graphQLConnection"; @@ -20,11 +23,30 @@ import { import { Types } from "mongoose"; let MONGOOSE_INSTANCE: typeof mongoose; -let testTag: TestUserTagType, testUser: TestUserType; +let testTag: TestUserTagType, + testUser: TestUserType, + testOrganization: TestOrganizationType, + randomUser: TestUserType; beforeAll(async () => { MONGOOSE_INSTANCE = await connect(); - [testUser, , [testTag]] = await createTagsAndAssignToUser(); + [testUser, testOrganization, [testTag]] = await createTagsAndAssignToUser(); + randomUser = await createTestUser(); + + await User.updateOne( + { + _id: randomUser?._id, + }, + { + joinedOrganizations: testOrganization?._id, + }, + ); + + await TagUser.create({ + tagId: testTag?._id, + userId: randomUser?._id, + organizationId: testTag?.organizationId, + }); }); afterAll(async () => { @@ -56,15 +78,26 @@ describe("usersAssignedTo resolver", () => { {}, ); - const tagUser = await TagUser.findOne({ + const tagUser1 = await TagUser.findOne({ tagId: testTag?._id, userId: testUser?._id, + organizationId: testTag?.organizationId, }); - const user = await User.findOne({ + const tagUser2 = await TagUser.findOne({ + tagId: testTag?._id, + userId: randomUser?._id, + organizationId: testTag?.organizationId, + }); + + const user1 = await User.findOne({ _id: testUser?._id, }); + const user2 = await User.findOne({ + _id: randomUser?._id, + }); + const totalCount = await TagUser.find({ tagId: testTag?._id, }).countDocuments(); @@ -72,15 +105,66 @@ describe("usersAssignedTo resolver", () => { expect(connection).toEqual({ edges: [ { - cursor: tagUser?._id.toString(), - node: user?.toObject(), + cursor: tagUser2?._id.toString(), + node: user2?.toObject(), + }, + { + cursor: tagUser1?._id.toString(), + node: user1?.toObject(), }, ], pageInfo: { - endCursor: tagUser?._id.toString(), + endCursor: tagUser1?._id.toString(), hasNextPage: false, hasPreviousPage: false, - startCursor: tagUser?._id.toString(), + startCursor: tagUser2?._id.toString(), + }, + totalCount, + }); + }); + + it(`returns the expected connection object, after a specified cursor`, async () => { + const tagUser1 = await TagUser.findOne({ + tagId: testTag?._id, + userId: testUser?._id, + }).lean(); + + const parent = testTag as InterfaceOrganizationTagUser; + const connection = await usersAssignedToResolver?.( + parent, + { + first: 1, + after: tagUser1?._id.toString(), + sortedBy: { id: "ASCENDING" }, + }, + {}, + ); + + const tagUser2 = await TagUser.findOne({ + tagId: testTag?._id, + userId: randomUser?._id, + }); + + const user2 = await User.findOne({ + _id: randomUser?._id, + }); + + const totalCount = await TagUser.find({ + tagId: testTag?._id, + }).countDocuments(); + + expect(connection).toEqual({ + edges: [ + { + cursor: tagUser2?._id.toString(), + node: user2?.toObject(), + }, + ], + pageInfo: { + endCursor: tagUser2?._id.toString(), + hasNextPage: false, + hasPreviousPage: true, + startCursor: tagUser2?._id.toString(), }, totalCount, }); diff --git a/tests/resolvers/UserTag/usersToAssignTo.spec.ts b/tests/resolvers/UserTag/usersToAssignTo.spec.ts new file mode 100644 index 0000000000..3b502b7db0 --- /dev/null +++ b/tests/resolvers/UserTag/usersToAssignTo.spec.ts @@ -0,0 +1,116 @@ +import "dotenv/config"; +import { + parseCursor, + usersToAssignTo as usersToAssignToResolver, +} from "../../../src/resolvers/UserTag/usersToAssignTo"; +import { connect, disconnect } from "../../helpers/db"; +import type mongoose from "mongoose"; +import { beforeAll, afterAll, describe, it, expect } from "vitest"; +import type { TestUserTagType } from "../../helpers/tags"; +import type { TestUserType } from "../../helpers/userAndOrg"; +import { createRootTagWithOrg } from "../../helpers/tags"; +import { GraphQLError } from "graphql"; +import type { DefaultGraphQLArgumentError } from "../../../src/utilities/graphQLConnection"; +import { User, type InterfaceOrganizationTagUser } from "../../../src/models"; +import { Types } from "mongoose"; + +let MONGOOSE_INSTANCE: typeof mongoose; +let testTag: TestUserTagType, testUser: TestUserType; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + [testUser, , testTag] = await createRootTagWithOrg(); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("usersToAssignTo resolver", () => { + it(`throws GraphQLError if invalid arguments are provided to the resolver`, async () => { + const parent = testTag as InterfaceOrganizationTagUser; + + try { + await usersToAssignToResolver?.(parent, {}, {}); + } catch (error) { + if (error instanceof GraphQLError) { + expect(error.extensions.code).toEqual("INVALID_ARGUMENTS"); + expect( + (error.extensions.errors as DefaultGraphQLArgumentError[]).length, + ).toBeGreaterThan(0); + } + } + }); + + it(`returns the expected connection object`, async () => { + const parent = testTag as InterfaceOrganizationTagUser; + + const connection = await usersToAssignToResolver?.( + parent, + { + first: 3, + }, + {}, + ); + + const user = await User.findOne({ + _id: testUser?._id, + }).lean(); + + const totalCount = 1; // only one user belonging to the organization + + expect(connection).toEqual({ + edges: [ + { + cursor: testUser?._id.toString(), + node: { + ...user, + _id: user?._id.toString(), + tagUsers: [], + }, + }, + ], + pageInfo: { + endCursor: testUser?._id.toString(), + hasNextPage: false, + hasPreviousPage: false, + startCursor: testUser?._id.toString(), + }, + totalCount, + }); + }); +}); + +describe("parseCursor function", () => { + it("returns failure state if argument cursorValue is an invalid cursor", async () => { + const result = await parseCursor({ + cursorName: "after", + cursorPath: ["after"], + cursorValue: new Types.ObjectId().toString(), + }); + + expect(result.isSuccessful).toEqual(false); + + if (result.isSuccessful === false) { + expect(result.errors.length).toBeGreaterThan(0); + } + }); + + it("returns success state if argument cursorValue is a valid cursor", async () => { + const parserCursorValue = await User.findOne({ + _id: testUser?._id, + }); + + const result = await parseCursor({ + cursorName: "after", + cursorPath: ["after"], + cursorValue: parserCursorValue?._id.toString() as string, + }); + + expect(result.isSuccessful).toEqual(true); + + if (result.isSuccessful === true) { + expect(result.parsedCursor).toEqual(parserCursorValue?._id.toString()); + } + }); +}); diff --git a/tests/resolvers/middleware/currentUserExists.spec.ts b/tests/resolvers/middleware/currentUserExists.spec.ts index 3cc0a4fced..0dd3707e89 100644 --- a/tests/resolvers/middleware/currentUserExists.spec.ts +++ b/tests/resolvers/middleware/currentUserExists.spec.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ import "dotenv/config"; import type mongoose from "mongoose"; import { Types } from "mongoose"; diff --git a/tests/services/createFile.spec.ts b/tests/services/createFile.spec.ts new file mode 100644 index 0000000000..7e096f966d --- /dev/null +++ b/tests/services/createFile.spec.ts @@ -0,0 +1,110 @@ +/** + * module - createFile + * + * This module contains unit tests for the `createFile` function in the file service. + * The tests utilize Vitest for mocking and asserting behavior. + * + * ### Tests + * + * - **Test Case 1**: `should create a new file document when no existing file is found` + * - Verifies that when a file with a specific hash does not exist, a new file document is created in the database. + * - It checks that `File.findOne` is called with the correct hash and that `File.create` is invoked with the expected file details. + * + * - **Test Case 2**: `should increment reference count if an existing file is found` + * - Confirms that if a file with the same hash already exists, the reference count for that file is incremented. + * - It ensures that the `save` method of the existing file is called and that `File.create` is not invoked. + * + * @example + * import \{ createFile \} from "./path/to/createFile"; + * + * const result = await createFile(uploadResult, originalname, mimetype, size); + * + * @see {@link ../../src/REST/services/file#createFile} + * @see {@link ../../src/models#File} + */ + +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { File } from "../../src/models"; +import { createFile } from "../../src/REST/services/file"; + +vi.mock("../../src/models", () => ({ + File: { + findOne: vi.fn(), + create: vi.fn(), + }, +})); + +describe("createFile", () => { + const uploadResult = { + hash: "testHash123", + objectKey: "test/file/path", + hashAlgorithm: "sha256", + exists: false, + }; + + const originalname = "image.png"; + const mimetype = "image/png"; + const size = 2048; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("should create a new file document when no existing file is found", async () => { + vi.mocked(File.findOne).mockResolvedValueOnce(null); + + const createdFile = File.create({ + fileName: originalname, + mimeType: mimetype, + size: size, + hash: { + value: uploadResult.hash, + algorithm: uploadResult.hashAlgorithm, + }, + uri: `http://localhost:3000/api/file/${uploadResult.objectKey}`, + metadata: { + objectKey: uploadResult.objectKey, + bucketName: "test-bucket", + }, + }); + + const result = await createFile(uploadResult, originalname, mimetype, size); + + expect(result).toEqual(createdFile); + expect(File.findOne).toHaveBeenCalledWith({ + "hash.value": uploadResult.hash, + }); + expect(File.create).toHaveBeenCalledWith({ + fileName: originalname, + mimeType: mimetype, + size: size, + hash: { + value: uploadResult.hash, + algorithm: uploadResult.hashAlgorithm, + }, + uri: expect.any(String), + metadata: { + objectKey: uploadResult.objectKey, + bucketName: expect.any(String), + }, + }); + }); + + it("should increment reference count if an existing file is found", async () => { + const existingFile = { + referenceCount: 1, + save: vi.fn().mockResolvedValueOnce(undefined), + }; + vi.mocked(File.findOne).mockResolvedValueOnce(existingFile); + + const result = await createFile(uploadResult, originalname, mimetype, size); + + expect(result).toEqual(existingFile); + expect(File.findOne).toHaveBeenCalledWith({ + "hash.value": uploadResult.hash, + }); + expect(existingFile.referenceCount).toBe(2); + expect(existingFile.save).toHaveBeenCalled(); + expect(File.create).not.toHaveBeenCalled(); + }); +}); diff --git a/tests/services/deleteFile.spec.ts b/tests/services/deleteFile.spec.ts new file mode 100644 index 0000000000..0acc40f036 --- /dev/null +++ b/tests/services/deleteFile.spec.ts @@ -0,0 +1,123 @@ +import { describe, it, expect, vi, beforeEach, beforeAll } from "vitest"; +import { File } from "../../src/models"; +import { deleteFile } from "../../src/REST/services/file"; +import * as minioServices from "../../src/REST/services/minio"; +import { BUCKET_NAME } from "../../src/config/minio"; +import { isMinioRunning } from "../helpers/minio"; + +vi.mock("../../src/models", () => ({ + File: { + findOne: vi.fn(), + deleteOne: vi.fn(), + prototype: { + save: vi.fn(), + }, + }, +})); + +vi.mock("../../src/REST/controllers/minio", () => ({ + deleteFile: vi.fn(), +})); + +describe("src -> REST -> services -> file -> deleteFile", () => { + const objectKey = "test/file/path"; + const fileId = "12345"; + let serverRunning = false; + + // Wait for server status check before running tests + beforeAll(async () => { + try { + serverRunning = await isMinioRunning(); + } catch (error) { + console.error("Error checking MinIO server status:", error); + serverRunning = false; + } + }); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("should return success:false and message if file is not found", async () => { + vi.mocked(File.findOne).mockResolvedValueOnce(null); + + const result = await deleteFile(objectKey, fileId); + + expect(result).toEqual({ success: false, message: "File not found." }); + expect(File.findOne).toHaveBeenCalledWith({ + _id: fileId, + "metadata.objectKey": objectKey, + }); + }); + + it("should decrement reference count if file exists and reference count is greater than 1", async () => { + const mockFile = { + referenceCount: 2, + save: vi.fn().mockResolvedValueOnce(undefined), + }; + vi.mocked(File.findOne).mockResolvedValueOnce(mockFile); + + const result = await deleteFile(objectKey, fileId); + + expect(result).toEqual({ + success: true, + message: "File reference count decreased successfully", + }); + expect(mockFile.referenceCount).toBe(1); + expect(mockFile.save).toHaveBeenCalled(); + }); + + // Use describe block with a dynamic condition + describe("MinIO server integration tests", () => { + beforeEach(async () => { + serverRunning = await isMinioRunning(); + }); + + it("should delete the file from the database and storage if reference count is 1", async () => { + // Skip this test if server is not running + if (!serverRunning) { + console.log("Skipping MinIO test - server not running"); + return; + } + + const mockFile = { + referenceCount: 1, + _id: fileId, + id: fileId, + }; + vi.mocked(File.findOne).mockResolvedValueOnce(mockFile); + + const deleteFileFromBucketSpy = vi.spyOn(minioServices, "deleteFile"); + + const result = await deleteFile(objectKey, fileId); + + expect(result).toEqual({ + success: true, + message: "File deleted successfully", + }); + expect(File.deleteOne).toHaveBeenCalledWith({ _id: fileId }); + expect(deleteFileFromBucketSpy).toHaveBeenCalledWith( + BUCKET_NAME, + objectKey, + ); + }); + }); + + it("should handle errors and return an error message", async () => { + const mockError = new Error("Deletion failed"); + vi.mocked(File.findOne).mockRejectedValueOnce(mockError); + + const consoleErrorSpy = vi.spyOn(console, "error"); + + const result = await deleteFile(objectKey, fileId); + + expect(result).toEqual({ + success: false, + message: "Error occurred while deleting file", + }); + expect(consoleErrorSpy).toHaveBeenCalledWith( + "Error deleting file:", + mockError, + ); + }); +}); diff --git a/tests/services/uploadFile.spec.ts b/tests/services/uploadFile.spec.ts new file mode 100644 index 0000000000..6c175fad99 --- /dev/null +++ b/tests/services/uploadFile.spec.ts @@ -0,0 +1,162 @@ +/** + * Tests for the file upload functionality. + * + * This test suite validates the uploadFile service which handles file uploads in the application. + * The service processes incoming files, validates their types, uploads them to storage, and creates + * corresponding database records. + * + * Test Coverage: + * - Input validation for missing files + * - MIME type validation for uploaded files + * - Successful file upload flow including storage and database operations + * - Error handling for upload failures + * + * Mock Strategy: + * - External services (uploadMedia, createFile) are mocked to isolate the upload logic + * - File validation utilities are mocked to control validation responses + * - Express Request/Response objects are mocked with necessary properties + * + * package - REST/services/file + */ + +import { describe, it, expect, vi, beforeEach } from "vitest"; +import type { Request, Response } from "express"; + +import { isValidMimeType } from "../../src/utilities/isValidMimeType"; +import { errors, requestContext } from "../../src/libraries"; +import { FILE_NOT_FOUND } from "../../src/constants"; +import { BUCKET_NAME } from "../../src/config/minio"; +import { createFile, uploadFile } from "../../src/REST/services/file"; +import { uploadMedia } from "../../src/REST/services/minio"; +import { Types } from "mongoose"; + +vi.mock("../../src/REST/services/minio", () => ({ + uploadMedia: vi.fn(), +})); + +vi.mock("../../src/REST/services/file/createFile", () => ({ + createFile: vi.fn(), +})); + +vi.mock("../../src/utilities/isValidMimeType", () => ({ + isValidMimeType: vi.fn(), +})); + +vi.mock("../../src/libraries/requestContext", () => ({ + translate: (message: string): string => `Translated ${message}`, +})); + +describe("uploadFile", () => { + const mockFile = { + buffer: Buffer.from("mock file content"), + mimetype: "image/png", + originalname: "test-image.png", + size: 1024, + }; + + const mockRequest = { + file: mockFile, + } as unknown as Request; + + const mockResponse = { + status: vi.fn().mockReturnThis(), + json: vi.fn(), + } as unknown as Response; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("should return error if no file is uploaded", async () => { + const reqWithoutFile = {} as Request; + + await expect(uploadFile(reqWithoutFile, mockResponse)).rejects.toThrow( + errors.InputValidationError, + ); + + expect(mockResponse.status).toHaveBeenCalledWith(400); + expect(mockResponse.json).toHaveBeenCalledWith({ + error: requestContext.translate(FILE_NOT_FOUND.MESSAGE), + }); + }); + + it("should return error if file type is invalid", async () => { + vi.mocked(isValidMimeType).mockReturnValueOnce(false); + + await expect(uploadFile(mockRequest, mockResponse)).rejects.toThrow( + errors.InputValidationError, + ); + + expect(isValidMimeType).toHaveBeenCalledWith(mockFile.mimetype); + }); + + it("should upload file and return file document data", async () => { + const mockUploadResult = { + hash: "mockhash", + objectKey: "mock-object-key", + hashAlgorithm: "SHA-256", + exists: false, + }; + + const mockFileDoc = { + _id: new Types.ObjectId(), + fileName: "test-image.png", + mimeType: "image/png", + size: 1024, + hash: { + value: "mockhash", + algorithm: "SHA-256", + }, + uri: "http://localhost/api/file/mock-object-key", + referenceCount: 1, + metadata: { + objectKey: "mock-object-key", + }, + encryption: false, + archived: false, + visibility: "PUBLIC" as const, + backupStatus: "", + status: "ACTIVE" as const, + createdAt: new Date(), + updatedAt: new Date(), + }; + + vi.mocked(isValidMimeType).mockReturnValueOnce(true); + vi.mocked(uploadMedia).mockResolvedValueOnce(mockUploadResult); + vi.mocked(createFile).mockResolvedValueOnce(mockFileDoc); + + const result = await uploadFile(mockRequest, mockResponse); + + expect(uploadMedia).toHaveBeenCalledWith( + BUCKET_NAME, + mockFile.buffer, + mockFile.originalname, + { ContentType: mockFile.mimetype }, + ); + expect(createFile).toHaveBeenCalledWith( + mockUploadResult, + mockFile.originalname, + mockFile.mimetype, + mockFile.size, + ); + expect(result).toEqual({ + uri: mockFileDoc.uri, + _id: mockFileDoc._id, + visibility: mockFileDoc.visibility, + objectKey: mockFileDoc.metadata.objectKey, + }); + }); + + it("should return an internal server error if upload fails", async () => { + const mockError = new Error("Failed to upload"); + + vi.mocked(isValidMimeType).mockReturnValueOnce(true); + vi.mocked(uploadMedia).mockRejectedValueOnce(mockError); + + await expect(uploadFile(mockRequest, mockResponse)).rejects.toThrow( + errors.InternalServerError, + ); + + expect(mockResponse.status).not.toHaveBeenCalledWith(400); + }); +}); diff --git a/tests/setup/superAdmin.spec.ts b/tests/setup/superAdmin.spec.ts index 7a4cf5826d..f3fe0c7b21 100644 --- a/tests/setup/superAdmin.spec.ts +++ b/tests/setup/superAdmin.spec.ts @@ -21,6 +21,29 @@ describe("Setup -> superAdmin", () => { vi.clearAllMocks(); }); + it("should validate the email and return an error message for invalid email", async () => { + const invalidEmail = "invalid-email"; + + vi.spyOn(inquirer, "prompt").mockImplementationOnce((questions: any) => { + // Assuming questions is an array + const questionArray = Array.isArray(questions) ? questions : [questions]; + const question = questionArray.find((q: any) => q.name === "email"); + const validate = question?.validate; + + if (typeof validate === "function") { + const validationResult = validate(invalidEmail); + return Promise.resolve({ + email: validationResult === true ? invalidEmail : validationResult, + }); + } + + return Promise.resolve({ email: invalidEmail }); + }); + + const result = await askForSuperAdminEmail.askForSuperAdminEmail(); + expect(result).toEqual("Invalid email. Please try again."); + }); + it("function askForSuperAdminEmail should return email as entered", async () => { const testEmail = "testemail@test.com"; vi.spyOn(inquirer, "prompt").mockImplementationOnce(() => diff --git a/tests/utilities/adminCheck.spec.ts b/tests/utilities/adminCheck.spec.ts index 84e2c41798..d5ba8b0662 100644 --- a/tests/utilities/adminCheck.spec.ts +++ b/tests/utilities/adminCheck.spec.ts @@ -16,6 +16,8 @@ import { AppUserProfile, Organization } from "../../src/models"; import { connect, disconnect } from "../helpers/db"; import type { TestOrganizationType, TestUserType } from "../helpers/userAndOrg"; import { createTestUserAndOrganization } from "../helpers/userAndOrg"; +import { adminCheck } from "../../src/utilities"; +import { requestContext } from "../../src/libraries"; let testUser: TestUserType; let testOrganization: TestOrganizationType; @@ -38,14 +40,11 @@ describe("utilities -> adminCheck", () => { }); it("throws error if userIsOrganizationAdmin === false and isUserSuperAdmin === false", async () => { - const { requestContext } = await import("../../src/libraries"); - const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => `Translated ${message}`); try { - const { adminCheck } = await import("../../src/utilities"); await adminCheck( testUser?._id, testOrganization ?? ({} as InterfaceOrganization), @@ -58,6 +57,16 @@ describe("utilities -> adminCheck", () => { expect(spy).toBeCalledWith(USER_NOT_AUTHORIZED_ADMIN.MESSAGE); }); + it("Returns boolean if userIsOrganizationAdmin === false and isUserSuperAdmin === false and throwError is false", async () => { + expect( + await adminCheck( + testUser?._id, + testOrganization ?? ({} as InterfaceOrganization), + false, + ), + ).toEqual(false); + }); + it("throws no error if userIsOrganizationAdmin === false and isUserSuperAdmin === true", async () => { const updatedUser = await AppUserProfile.findOneAndUpdate( { @@ -72,12 +81,11 @@ describe("utilities -> adminCheck", () => { }, ); - const { adminCheck } = await import("../../src/utilities"); - await expect( adminCheck( updatedUser?.userId?.toString() ?? "", testOrganization ?? ({} as InterfaceOrganization), + false, ), ).resolves.not.toThrowError(); }); @@ -98,8 +106,6 @@ describe("utilities -> adminCheck", () => { }, ); - const { adminCheck } = await import("../../src/utilities"); - await expect( adminCheck( testUser?._id, @@ -108,14 +114,11 @@ describe("utilities -> adminCheck", () => { ).resolves.not.toThrowError(); }); it("throws error if user is not found with the specific Id", async () => { - const { requestContext } = await import("../../src/libraries"); - const spy = vi .spyOn(requestContext, "translate") .mockImplementationOnce((message) => `Translated ${message}`); try { - const { adminCheck } = await import("../../src/utilities"); await adminCheck( new mongoose.Types.ObjectId(), testOrganization ?? ({} as InterfaceOrganization), diff --git a/tests/utilities/auth.spec.ts b/tests/utilities/auth.spec.ts index b3c4d84a47..faef0f4d76 100644 --- a/tests/utilities/auth.spec.ts +++ b/tests/utilities/auth.spec.ts @@ -2,7 +2,7 @@ import jwt from "jsonwebtoken"; import type mongoose from "mongoose"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import type { InterfaceAppUserProfile, InterfaceUser } from "../../src/models"; -import { AppUserProfile } from "../../src/models"; +import { AppUserProfile, Community } from "../../src/models"; import { createAccessToken, createRefreshToken, @@ -17,6 +17,7 @@ let user: TestUserType; let appUserProfile: TestAppUserProfileType; let MONGOOSE_INSTANCE: typeof mongoose; export interface InterfaceJwtTokenPayload { + timeout: number; tokenVersion: number; userId: string; firstName: string; @@ -37,8 +38,54 @@ afterAll(async () => { }); describe("createAccessToken", () => { + it("should use the timeout from the Community document if it exists", async () => { + // Set up a Community document with a specific timeout + const community = await Community.create({ + name: "Test Community", + timeout: 45, // Custom timeout in minutes + }); + + const token = await createAccessToken( + user ? user.toObject() : ({} as InterfaceUser), + appUserProfile + ? appUserProfile.toObject() + : ({} as InterfaceAppUserProfile), + ); + + expect(token).toBeDefined(); + + const decodedToken = jwt.decode(token); + + expect(decodedToken).not.toBeNull(); + expect((decodedToken as InterfaceJwtTokenPayload).timeout).toBe( + community.timeout, + ); + + // Clean up + await Community.deleteMany({}); + }); + + it("should default to 30 minutes if no Community document exists", async () => { + // Ensure no Community documents exist + await Community.deleteMany({}); + + const token = await createAccessToken( + user ? user.toObject() : ({} as InterfaceUser), + appUserProfile + ? appUserProfile.toObject() + : ({} as InterfaceAppUserProfile), + ); + + expect(token).toBeDefined(); + + const decodedToken = jwt.decode(token); + + expect(decodedToken).not.toBeNull(); + expect((decodedToken as InterfaceJwtTokenPayload).timeout).toBe(30); + }); + it("should create a JWT token with the correct payload", async () => { - const token = createAccessToken( + const token = await createAccessToken( user ? user.toObject() : ({} as InterfaceUser), appUserProfile ? appUserProfile.toObject() diff --git a/tests/utilities/checks.spec.ts b/tests/utilities/checks.spec.ts new file mode 100644 index 0000000000..6cf1f3744e --- /dev/null +++ b/tests/utilities/checks.spec.ts @@ -0,0 +1,156 @@ +import "dotenv/config"; +import type mongoose from "mongoose"; +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; +import { + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR, + EVENT_VOLUNTEER_NOT_FOUND_ERROR, + USER_NOT_AUTHORIZED_ERROR, + USER_NOT_FOUND_ERROR, +} from "../../src/constants"; + +import type { InterfaceUser } from "../../src/models"; +import { AppUserProfile, VolunteerMembership } from "../../src/models"; +import { connect, disconnect } from "../helpers/db"; +import type { TestUserType } from "../helpers/userAndOrg"; +import { requestContext } from "../../src/libraries"; +import { + checkAppUserProfileExists, + checkEventVolunteerExists, + checkUserExists, + checkVolunteerGroupExists, + checkVolunteerMembershipExists, +} from "../../src/utilities/checks"; +import { createTestUser } from "../helpers/user"; +import { createVolunteerAndActions } from "../helpers/volunteers"; +import type { TestEventVolunteerType } from "../helpers/events"; +import type { TestEventVolunteerGroupType } from "../resolvers/Mutation/createEventVolunteer.spec"; + +let randomUser: InterfaceUser; +let testUser: TestUserType; +let testVolunteer: TestEventVolunteerType; +let testGroup: TestEventVolunteerGroupType; +let MONGOOSE_INSTANCE: typeof mongoose; + +const expectError = async ( + fn: () => Promise, + expectedMessage: string, +): Promise => { + const spy = vi + .spyOn(requestContext, "translate") + .mockImplementationOnce((message) => `Translated ${message}`); + + try { + await fn(); + } catch (error: unknown) { + expect((error as Error).message).toEqual(`Translated ${expectedMessage}`); + } + + expect(spy).toBeCalledWith(expectedMessage); +}; + +beforeAll(async () => { + MONGOOSE_INSTANCE = await connect(); + + const [, , user1, , volunteer1, , volunteerGroup] = + await createVolunteerAndActions(); + + testUser = user1; + testVolunteer = volunteer1; + testGroup = volunteerGroup; + + randomUser = (await createTestUser()) as InterfaceUser; + await AppUserProfile.deleteOne({ + userId: randomUser._id, + }); +}); + +afterAll(async () => { + await disconnect(MONGOOSE_INSTANCE); +}); + +describe("utilities -> checks", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("checkUserExists -> invalid userId", async () => { + await expectError( + () => checkUserExists(testUser?.appUserProfileId), + USER_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("checkUserExists -> valid userId", async () => { + expect((await checkUserExists(testUser?._id))._id).toEqual(testUser?._id); + }); + + it("checkAppUserProfileExists -> unauthorized user", async () => { + await expectError( + () => checkAppUserProfileExists(randomUser), + USER_NOT_AUTHORIZED_ERROR.MESSAGE, + ); + }); + + it("checkAppUserProfileExists -> authorized user", async () => { + expect( + (await checkAppUserProfileExists(testUser as InterfaceUser)).userId, + ).toEqual(testUser?._id); + }); + + it("checkEventVolunteerExists -> invalid volunteerId", async () => { + await expectError( + () => checkEventVolunteerExists(testUser?._id), + EVENT_VOLUNTEER_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("checkEventVolunteerExists -> valid volunteerId", async () => { + expect((await checkEventVolunteerExists(testVolunteer?._id))._id).toEqual( + testVolunteer?._id, + ); + }); + + it("checkVolunteerGroupExists -> invalid groupId", async () => { + await expectError( + () => checkVolunteerGroupExists(testUser?._id), + EVENT_VOLUNTEER_GROUP_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("checkVolunteerGroupExists -> valid groupId", async () => { + expect((await checkVolunteerGroupExists(testGroup?._id))._id).toEqual( + testGroup?._id, + ); + }); + + it("checkVolunteerMembershipExists -> invalid membershipId", async () => { + await expectError( + () => checkVolunteerMembershipExists(testUser?._id), + EVENT_VOLUNTEER_MEMBERSHIP_NOT_FOUND_ERROR.MESSAGE, + ); + }); + + it("checkVolunteerMembershipExists -> valid membershipId", async () => { + const volunteerMembership = await VolunteerMembership.create({ + event: testVolunteer?._id, + volunteer: testUser?._id, + status: "invited", + }); + expect( + ( + await checkVolunteerMembershipExists( + volunteerMembership?._id.toString(), + ) + )._id, + ).toEqual(volunteerMembership?._id); + }); +}); diff --git a/tests/utilities/createSampleOrganizationUtil.spec.ts b/tests/utilities/createSampleOrganizationUtil.spec.ts index 6e33feab9c..d2c3ccff07 100644 --- a/tests/utilities/createSampleOrganizationUtil.spec.ts +++ b/tests/utilities/createSampleOrganizationUtil.spec.ts @@ -114,7 +114,6 @@ describe("generatePostData function", () => { expect(post.title).toEqual(expect.any(String)); expect(post.creatorId).toEqual(expect.any(Object)); expect(post.organization).toEqual(expect.any(Object)); - expect(post.imageUrl).toEqual(expect.any(String)); expect(post.createdAt).toEqual(expect.any(Date)); }); diff --git a/tests/utilities/deletePreviousFile.spec.ts b/tests/utilities/deletePreviousFile.spec.ts new file mode 100644 index 0000000000..d48d2e8859 --- /dev/null +++ b/tests/utilities/deletePreviousFile.spec.ts @@ -0,0 +1,94 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import type { InterfaceFile } from "../../src/models"; +import { File } from "../../src/models"; +import { deleteFile } from "../../src/REST/services/minio"; +import { BUCKET_NAME } from "../../src/config/minio"; +import { deletePreviousFile } from "../../src/utilities/encodedImageStorage/deletePreviousFile"; +import type { DeleteObjectCommandOutput } from "@aws-sdk/client-s3"; +import type { Document } from "mongoose"; + +type FileDocument = InterfaceFile & Document; + +vi.mock("../../src/models", () => ({ + File: { + findOne: vi.fn(), + deleteOne: vi.fn(), + findOneAndUpdate: vi.fn(), + }, +})); + +vi.mock("../../src/REST/services/minio", () => ({ + deleteFile: vi.fn(), +})); + +describe("deletePreviousFile", () => { + const mockFileId = "test-file-id"; + const mockObjectKey = "test-object-key"; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + afterEach(() => { + vi.resetAllMocks(); + }); + + it("should delete file and record when referenceCount is 1", async () => { + vi.mocked(File.findOne).mockResolvedValueOnce({ + referenceCount: 1, + } as FileDocument); + + vi.mocked(File.deleteOne).mockResolvedValueOnce({ + acknowledged: true, + deletedCount: 1, + }); + vi.mocked(deleteFile).mockResolvedValueOnce({ + $metadata: {}, + } as DeleteObjectCommandOutput); + + await deletePreviousFile(mockFileId, mockObjectKey); + + expect(File.findOne).toHaveBeenCalledWith({ + _id: mockFileId, + }); + + expect(deleteFile).toHaveBeenCalledWith(BUCKET_NAME, mockObjectKey); + + expect(File.deleteOne).toHaveBeenCalledWith({ + _id: mockFileId, + }); + + expect(File.findOneAndUpdate).not.toHaveBeenCalled(); + }); + + it("should decrement referenceCount when greater than 1", async () => { + vi.mocked(File.findOne).mockResolvedValueOnce({ + referenceCount: 2, + } as FileDocument); + + vi.mocked(File.findOneAndUpdate).mockResolvedValueOnce({ + referenceCount: 1, + } as FileDocument); + + await deletePreviousFile(mockFileId, mockObjectKey); + + expect(File.findOne).toHaveBeenCalledWith({ + _id: mockFileId, + }); + + expect(deleteFile).not.toHaveBeenCalled(); + + expect(File.deleteOne).not.toHaveBeenCalled(); + + expect(File.findOneAndUpdate).toHaveBeenCalledWith( + { + _id: mockFileId, + }, + { + $inc: { + referenceCount: -1, + }, + }, + ); + }); +}); diff --git a/tests/utilities/isValidMimeType.spec.ts b/tests/utilities/isValidMimeType.spec.ts new file mode 100644 index 0000000000..f93a10aee9 --- /dev/null +++ b/tests/utilities/isValidMimeType.spec.ts @@ -0,0 +1,23 @@ +import { describe, it, expect } from "vitest"; +import { isValidMimeType } from "../../src/utilities/isValidMimeType"; + +describe("isValidMimeType", () => { + it("should return true for valid image mime types", () => { + expect(isValidMimeType("image/jpeg")).toBe(true); + expect(isValidMimeType("image/png")).toBe(true); + expect(isValidMimeType("image/gif")).toBe(true); + expect(isValidMimeType("image/webp")).toBe(true); + }); + + it("should return true for valid video mime types", () => { + expect(isValidMimeType("video/mp4")).toBe(true); + }); + + it("should return false for invalid mime types", () => { + expect(isValidMimeType("image/bmp")).toBe(false); + expect(isValidMimeType("video/webm")).toBe(false); + expect(isValidMimeType("application/pdf")).toBe(false); + expect(isValidMimeType("")).toBe(false); + expect(isValidMimeType("invalid-mime-type")).toBe(false); + }); +}); diff --git a/tests/utilities/userTagsPaginationUtils.spec.ts b/tests/utilities/userTagsPaginationUtils.spec.ts new file mode 100644 index 0000000000..be910d02ba --- /dev/null +++ b/tests/utilities/userTagsPaginationUtils.spec.ts @@ -0,0 +1,350 @@ +import { describe, expect, it } from "vitest"; +import { + parseUserTagSortedBy, + parseUserTagMemberWhere, + parseUserTagWhere, + getUserTagGraphQLConnectionSort, + getUserTagMemberGraphQLConnectionFilter, + getUserTagGraphQLConnectionFilter, +} from "../../src/utilities/userTagsPaginationUtils"; +import type { SortedByOrder } from "../../src/types/generatedGraphQLTypes"; +import { Types } from "mongoose"; + +describe("parseUserTagWhere function", () => { + it("returns the failure state if name isn't provided", async () => { + const result = await parseUserTagWhere({}); + expect(result.isSuccessful).toEqual(false); + }); + + it("returns the failure state if provided name.starts_with isn't a string", async () => { + const result = await parseUserTagWhere({ + name: { + starts_with: Math.random() as unknown as string, + }, + }); + + expect(result.isSuccessful).toEqual(false); + }); + + it("returns the success state if where input is nullish", async () => { + const result = await parseUserTagWhere(undefined); + + expect(result.isSuccessful).toEqual(true); + }); + + it("returns the success state if provided name.starts_with is an empty string", async () => { + const result = await parseUserTagWhere({ + name: { + starts_with: "", + }, + }); + + expect(result.isSuccessful).toEqual(true); + }); +}); + +describe("parseUserTagMemberWhere function", () => { + it("returns the failure state if neither firstName nor lastName is provided", async () => { + const result = await parseUserTagMemberWhere({}); + + expect(result.isSuccessful).toEqual(false); + }); + + it("returns the failure state if firstName isn't a string", async () => { + const result = await parseUserTagMemberWhere({ + firstName: { starts_with: Math.random() as unknown as string }, + }); + + expect(result.isSuccessful).toEqual(false); + }); + + it("returns the failure state if lastName isn't a string", async () => { + const result = await parseUserTagMemberWhere({ + firstName: { starts_with: "firstName" }, + lastName: { starts_with: Math.random() as unknown as string }, + }); + + expect(result.isSuccessful).toEqual(false); + }); + + it("returns the success state if where input is nullish", async () => { + const result = await parseUserTagMemberWhere(undefined); + + expect(result.isSuccessful).toEqual(true); + }); + + it("returns the success state if provided firstName is provided and lastName isn't", async () => { + const result = await parseUserTagMemberWhere({ + firstName: { starts_with: "firstName" }, + }); + + expect(result.isSuccessful).toEqual(true); + }); + + it("returns the success state if provided lastName is provided and firstName isn't", async () => { + const result = await parseUserTagMemberWhere({ + lastName: { starts_with: "lastName" }, + }); + + expect(result.isSuccessful).toEqual(true); + }); + + it("returns the success state if provided names are non-empty and valid strings", async () => { + const result = await parseUserTagMemberWhere({ + firstName: { starts_with: "firstName" }, + lastName: { starts_with: "lastName" }, + }); + + expect(result.isSuccessful).toEqual(true); + }); +}); + +describe("parseUserTagSortedBy function", () => { + it("returns the failure state if provided sortedBy isn't of type SortedByOrder", async () => { + const result = await parseUserTagSortedBy({ + id: "" as unknown as SortedByOrder, + }); + + expect(result.isSuccessful).toEqual(false); + }); + + it("returns the success state if where input is nullish", async () => { + const result = await parseUserTagSortedBy(undefined); + + expect(result.isSuccessful).toEqual(true); + }); + + it("returns the success state if provided sort order is valid", async () => { + const result = await parseUserTagSortedBy({ + id: "ASCENDING", + }); + + expect(result.isSuccessful).toEqual(true); + }); +}); + +describe("getUserTagGraphQLConnectionFilter function", () => { + it(`when sort order is "ASCENDING" argument cursor is non-null and argument direction corresponds to backward`, async () => { + const cursor = "cursor"; + + expect( + getUserTagGraphQLConnectionFilter({ + cursor, + direction: "BACKWARD", + sortById: "ASCENDING", + nameStartsWith: "userName", + }), + ).toEqual({ + _id: { + $lt: cursor, + }, + name: { + $regex: /^userName/i, + }, + }); + }); + + it(`when sort order is "ASCENDING" argument cursor is non-null and argument direction corresponds to forward`, async () => { + const cursor = "cursor"; + + expect( + getUserTagGraphQLConnectionFilter({ + cursor, + direction: "FORWARD", + sortById: "ASCENDING", + nameStartsWith: "userName", + }), + ).toEqual({ + _id: { + $gt: cursor, + }, + name: { + $regex: /^userName/i, + }, + }); + }); + + it(`when sort order is "DESCENDING" argument cursor is non-null and argument direction corresponds to backward`, async () => { + const cursor = "cursor"; + + expect( + getUserTagGraphQLConnectionFilter({ + cursor, + direction: "BACKWARD", + sortById: "DESCENDING", + nameStartsWith: "userName", + }), + ).toEqual({ + _id: { + $gt: cursor, + }, + name: { + $regex: /^userName/i, + }, + }); + }); + + it(`when sort order is "DESCENDING" argument cursor is non-null and argument direction corresponds to forward`, async () => { + const cursor = "cursor"; + + expect( + getUserTagGraphQLConnectionFilter({ + cursor, + direction: "FORWARD", + sortById: "DESCENDING", + nameStartsWith: "userName", + }), + ).toEqual({ + _id: { + $lt: cursor, + }, + name: { + $regex: /^userName/i, + }, + }); + }); +}); + +describe("getUserTagMemberGraphQLConnectionFilter function", () => { + it(`when sort order is "ASCENDING" argument cursor is non-null and argument direction corresponds to backward`, async () => { + const cursor = new Types.ObjectId().toString(); + + expect( + getUserTagMemberGraphQLConnectionFilter({ + cursor, + direction: "BACKWARD", + sortById: "ASCENDING", + firstNameStartsWith: "firstName", + lastNameStartsWith: "lastName", + }), + ).toEqual({ + _id: { + $lt: new Types.ObjectId(cursor), + }, + firstName: { + $regex: /^firstName/i, + }, + lastName: { + $regex: /^lastName/i, + }, + }); + }); + + it(`when sort order is "ASCENDING" argument cursor is non-null and argument direction corresponds to forward`, async () => { + const cursor = new Types.ObjectId().toString(); + + expect( + getUserTagMemberGraphQLConnectionFilter({ + cursor, + direction: "FORWARD", + sortById: "ASCENDING", + firstNameStartsWith: "firstName", + lastNameStartsWith: "lastName", + }), + ).toEqual({ + _id: { + $gt: new Types.ObjectId(cursor), + }, + firstName: { + $regex: /^firstName/i, + }, + lastName: { + $regex: /^lastName/i, + }, + }); + }); + + it(`when sort order is "DESCENDING" argument cursor is non-null and argument direction corresponds to backward`, async () => { + const cursor = new Types.ObjectId().toString(); + + expect( + getUserTagMemberGraphQLConnectionFilter({ + cursor, + direction: "BACKWARD", + sortById: "DESCENDING", + firstNameStartsWith: "firstName", + lastNameStartsWith: "lastName", + }), + ).toEqual({ + _id: { + $gt: new Types.ObjectId(cursor), + }, + firstName: { + $regex: /^firstName/i, + }, + lastName: { + $regex: /^lastName/i, + }, + }); + }); + + it(`when sort order is "DESCENDING" argument cursor is non-null and argument direction corresponds to forward`, async () => { + const cursor = new Types.ObjectId().toString(); + + expect( + getUserTagMemberGraphQLConnectionFilter({ + cursor, + direction: "FORWARD", + sortById: "DESCENDING", + firstNameStartsWith: "firstName", + lastNameStartsWith: "lastName", + }), + ).toEqual({ + _id: { + $lt: new Types.ObjectId(cursor), + }, + firstName: { + $regex: /^firstName/i, + }, + lastName: { + $regex: /^lastName/i, + }, + }); + }); +}); + +describe("getUserTagGraphQLConnectionSort function", () => { + it(`when sort order is "ASCENDING" and argument direction corresponds to backward`, async () => { + expect( + getUserTagGraphQLConnectionSort({ + direction: "BACKWARD", + sortById: "ASCENDING", + }), + ).toEqual({ + _id: -1, + }); + }); + + it(`when sort order is "ASCENDING" and argument direction corresponds to forward`, async () => { + expect( + getUserTagGraphQLConnectionSort({ + direction: "FORWARD", + sortById: "ASCENDING", + }), + ).toEqual({ + _id: 1, + }); + }); + + it(`when sort order is "DESCENDING" and argument direction corresponds to backward`, async () => { + expect( + getUserTagGraphQLConnectionSort({ + direction: "BACKWARD", + sortById: "DESCENDING", + }), + ).toEqual({ + _id: 1, + }); + }); + + it(`when sort order is "DESCENDING" and argument direction corresponds to forward`, async () => { + expect( + getUserTagGraphQLConnectionSort({ + direction: "FORWARD", + sortById: "DESCENDING", + }), + ).toEqual({ + _id: -1, + }); + }); +});