From a36348ead1935e5946b063666d1bcadcd1c43545 Mon Sep 17 00:00:00 2001 From: Sylvain Zimmer Date: Fri, 9 Jan 2026 00:51:25 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89(all)=20bootstrap=20the=20Calendars?= =?UTF-8?q?=20project?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This repository was forked from Drive in late December 2025 and boostraped as a minimal demo of backend+caldav server+frontend integration. There is much left to do and to fix! --- .cursor/rules/django-python.mdc | 77 + .github/ISSUE_TEMPLATE.md | 6 + .github/ISSUE_TEMPLATE/Bug_report.md | 28 + .github/ISSUE_TEMPLATE/Feature_request.md | 23 + .github/ISSUE_TEMPLATE/Support_question.md | 22 + .github/PULL_REQUEST_TEMPLATE.md | 11 + .github/workflows/calendars-frontend.yml | 114 + .github/workflows/calendars.yml | 187 + .github/workflows/crowdin_download.yml | 76 + .github/workflows/crowdin_upload.yml | 68 + .github/workflows/docker-hub.yml | 104 + .../front-dependencies-installation.yml | 36 + .gitignore | 84 + .gitlint | 78 + CODE_OF_CONDUCT.md | 79 + CONTRIBUTING.md | 84 + LICENSE | 21 + Makefile | 369 + Procfile | 3 + README.md | 155 + SECURITY.md | 23 + bin/_config.sh | 93 + bin/clear_db_e2e.sql | 9 + bin/compose | 6 + bin/fernetkey | 6 + bin/manage | 6 + bin/postgres_e2e | 12 + bin/pylint | 38 + bin/pytest | 8 + bin/scalingo_postcompile | 11 + bin/scalingo_postfrontend | 15 + bin/scalingo_run_web | 15 + bin/update_app_cacert.sh | 17 + bin/update_openapi_schema | 12 + compose.yaml | 183 + cron.json | 7 + docker/auth/realm.json | 2358 +++++ docker/davical/Dockerfile | 39 + docker/davical/config.php | 64 + docker/davical/davical.conf | 22 + docker/davical/run-migrations | 93 + .../development/etc/nginx/conf.d/default.conf | 28 + .../init-databases.sh | 46 + docker/files/etc/nginx/conf.d/default.conf | 15 + docker/postgresql/init-databases.sh | 36 + docs/architecture.md | 210 + env.d/development/backend.defaults | 70 + env.d/development/crowdin.defaults | 0 env.d/development/davical.defaults | 13 + env.d/development/frontend.defaults | 2 + env.d/development/keycloak.defaults | 13 + env.d/development/postgresql.defaults | 4 + env.d/development/postgresql.e2e | 11 + gitlint/gitlint_emoji.py | 37 + renovate.json | 25 + src/backend/.dockerignore | 33 + src/backend/.pylintrc | 472 + src/backend/Dockerfile | 158 + src/backend/MANIFEST.in | 3 + src/backend/__init__.py | 0 src/backend/calendars/__init__.py | 5 + src/backend/calendars/celery_app.py | 26 + .../configuration/theme/default.json | 69 + src/backend/calendars/settings.py | 919 ++ src/backend/calendars/urls.py | 58 + src/backend/calendars/wsgi.py | 17 + src/backend/core/__init__.py | 0 src/backend/core/admin.py | 93 + src/backend/core/api/__init__.py | 34 + src/backend/core/api/fields.py | 25 + src/backend/core/api/permissions.py | 79 + src/backend/core/api/serializers.py | 155 + src/backend/core/api/viewsets.py | 397 + src/backend/core/api/viewsets_caldav.py | 220 + src/backend/core/apps.py | 19 + src/backend/core/authentication/__init__.py | 52 + src/backend/core/authentication/backends.py | 54 + src/backend/core/authentication/exceptions.py | 5 + src/backend/core/authentication/views.py | 25 + src/backend/core/enums.py | 12 + src/backend/core/external_api/permissions.py | 41 + src/backend/core/external_api/viewsets.py | 36 + src/backend/core/factories.py | 28 + .../core/management/commands/__init__.py | 0 .../management/commands/createsuperuser.py | 47 + src/backend/core/migrations/0001_initial.py | 90 + src/backend/core/migrations/__init__.py | 0 src/backend/core/models.py | 402 + src/backend/core/services/__init__.py | 0 src/backend/core/services/caldav_service.py | 477 + src/backend/core/signals.py | 55 + src/backend/core/templatetags/__init__.py | 0 src/backend/core/templatetags/extra_tags.py | 58 + src/backend/core/tests/__init__.py | 0 .../core/tests/authentication/__init__.py | 0 .../tests/authentication/test_backends.py | 579 ++ .../core/tests/authentication/test_views.py | 66 + src/backend/core/tests/conftest.py | 148 + .../external_api/test_external_api_users.py | 152 + src/backend/core/tests/swagger/__init__.py | 0 .../core/tests/swagger/test_openapi_schema.py | 42 + src/backend/core/tests/test_api_config.py | 161 + src/backend/core/tests/test_api_users.py | 638 ++ src/backend/core/tests/test_caldav_service.py | 71 + src/backend/core/tests/test_models_users.py | 46 + src/backend/core/tests/test_settings.py | 30 + src/backend/core/tests/utils/urls.py | 20 + src/backend/core/urls.py | 61 + src/backend/e2e/__init__.py | 0 .../e2e/management/commands/__init__.py | 0 src/backend/e2e/serializers.py | 12 + src/backend/e2e/tests/test_api_e2e.py | 83 + src/backend/e2e/urls.py | 26 + src/backend/e2e/utils.py | 11 + src/backend/e2e/viewsets.py | 40 + src/backend/entrypoint | 35 + src/backend/gunicorn.conf.py | 16 + .../locale/de_DE/LC_MESSAGES/django.po | 455 + .../locale/en_US/LC_MESSAGES/django.po | 362 + .../locale/fr_FR/LC_MESSAGES/django.po | 371 + .../locale/nl_NL/LC_MESSAGES/django.po | 369 + src/backend/manage.py | 15 + src/backend/pyproject.toml | 145 + src/backend/uv.lock | 1836 ++++ src/frontend/.dockerignore | 29 + src/frontend/Dockerfile | 72 + src/frontend/apps/calendars/.env | 1 + src/frontend/apps/calendars/.env.development | 1 + src/frontend/apps/calendars/.gitignore | 41 + src/frontend/apps/calendars/README.md | 40 + .../apps/calendars/__mocks__/fileMock.js | 2 + src/frontend/apps/calendars/conf/default.conf | 26 + src/frontend/apps/calendars/cunningham.ts | 411 + src/frontend/apps/calendars/eslint.config.mjs | 22 + src/frontend/apps/calendars/jest.config.ts | 39 + src/frontend/apps/calendars/next.config.ts | 21 + src/frontend/apps/calendars/package.json | 54 + .../public/assets/401-background.png | Bin 0 -> 264501 bytes .../public/assets/403-background.png | Bin 0 -> 273754 bytes .../calendars/public/assets/anct_favicon.png | Bin 0 -> 1176 bytes .../public/assets/anct_logo-icon.svg | 16 + .../public/assets/anct_logo_alpha.svg | 7 + .../public/assets/anct_logo_beta.svg | 26 + .../apps/calendars/public/assets/favicon.png | Bin 0 -> 670 bytes .../public/assets/logo-icon_alpha.svg | 13 + .../public/assets/logo-icon_beta.svg | 16 + .../public/assets/logo-suite-numerique.png | Bin 0 -> 11214 bytes .../calendars/public/assets/logo_alpha.svg | 6 + .../apps/calendars/public/mime-video.svg | 68 + .../calendars/src/assets/feedback/form.svg | 3 + .../calendars/src/assets/feedback/tchap.svg | 3 + .../calendars/src/assets/feedback/visio.svg | 3 + .../calendars/src/assets/icons/cancel.svg | 3 + .../src/assets/icons/cancel_blue.svg | 3 + .../src/assets/icons/delete_filled.svg | 3 + .../apps/calendars/src/assets/icons/info.svg | 3 + .../calendars/src/assets/icons/settings.svg | 3 + .../apps/calendars/src/assets/icons/trash.svg | 3 + .../apps/calendars/src/assets/icons/undo.svg | 3 + .../calendars/src/assets/icons/undo_blue.svg | 3 + .../apps/calendars/src/assets/logo-gouv.svg | 454 + .../apps/calendars/src/assets/logo-icon.svg | 4 + .../features/analytics/AnalyticsProvider.tsx | 7 + .../calendars/src/features/api/APIError.ts | 57 + .../calendars/src/features/api/fetchApi.ts | 67 + .../apps/calendars/src/features/api/types.ts | 18 + .../apps/calendars/src/features/api/utils.ts | 39 + .../apps/calendars/src/features/auth/Auth.tsx | 76 + .../features/auth/components/LoginButton.tsx | 23 + .../features/auth/components/LogoutButton.tsx | 12 + .../apps/calendars/src/features/auth/types.ts | 12 + .../calendars/src/features/calendar/api.ts | 51 + .../calendar/components/CalendarList.scss | 99 + .../calendar/components/CalendarList.tsx | 88 + .../calendar/components/CalendarView.scss | 171 + .../calendar/components/CalendarView.tsx | 209 + .../components/CreateCalendarModal.tsx | 112 + .../calendar/components/EventModal.scss | 90 + .../calendar/components/EventModal.tsx | 441 + .../calendar/components/EventModalAdapter.tsx | 115 + .../calendar/components/LeftPanel.scss | 23 + .../calendar/components/LeftPanel.tsx | 43 + .../calendar/components/MiniCalendar.scss | 103 + .../calendar/components/MiniCalendar.tsx | 108 + .../calendar/components/RecurrenceEditor.scss | 56 + .../calendar/components/RecurrenceEditor.tsx | 199 + .../src/features/calendar/components/index.ts | 4 + .../features/calendar/hooks/useCalendars.ts | 52 + .../calendar/hooks/useCreateEventModal.tsx | 45 + .../features/calendar/hooks/useEventModal.tsx | 102 + .../calendars/src/features/calendar/types.ts | 34 + .../calendars/src/features/config/Config.ts | 0 .../src/features/config/ConfigProvider.tsx | 46 + .../src/features/config/useApiConfig.ts | 14 + .../calendars/src/features/errors/AppError.ts | 1 + .../src/features/feedback/Feedback.scss | 75 + .../src/features/feedback/Feedback.tsx | 193 + .../features/feedback/useMessagesWidget.tsx | 72 + .../features/forms/components/RhfInput.tsx | 49 + .../apps/calendars/src/features/i18n/conf.ts | 2 + .../calendars/src/features/i18n/initI18n.ts | 52 + .../src/features/i18n/translations.json | 634 ++ .../apps/calendars/src/features/i18n/utils.ts | 12 + .../components/global/GlobalLayout.scss | 9 + .../components/global/GlobalLayout.tsx | 8 + .../layouts/components/header/Header.tsx | 92 + .../layouts/components/header/index.scss | 34 + .../left-panel/LeftPanelMobile.scss | 18 + .../components/left-panel/LeftPanelMobile.tsx | 20 + .../components/simple/SimpleLayout.tsx | 32 + .../ui/components/breadcrumbs/Breadcrumbs.tsx | 58 + .../ui/components/breadcrumbs/index.scss | 41 + .../circular-progress/CircularProgress.tsx | 90 + .../features/ui/components/gaufre/Gaufre.tsx | 28 + .../generic-disclaimer/GenericDisclaimer.scss | 25 + .../generic-disclaimer/GenericDisclaimer.tsx | 24 + .../src/features/ui/components/icon/Icon.tsx | 26 + .../infinite-scroll/InfiniteScroll.scss | 12 + .../infinite-scroll/InfiniteScroll.tsx | 86 + .../ui/components/infinite-scroll/index.ts | 1 + .../features/ui/components/info/InfoRow.scss | 19 + .../features/ui/components/info/InfoRow.tsx | 21 + .../components/responsive/ResponsiveDivs.tsx | 15 + .../ui/components/responsive/index.scss | 12 + .../ui/components/spinner/SpinnerPage.scss | 6 + .../ui/components/spinner/SpinnerPage.tsx | 9 + .../ui/components/toaster/Toaster.tsx | 57 + .../features/ui/components/toaster/index.scss | 46 + .../ui/components/user/UserProfile.tsx | 23 + .../ui/cunningham/useCunninghamTheme.ts | 15 + .../features/users/hooks/useUserQueries.tsx | 27 + .../calendars/src/features/users/types.ts | 6 + .../src/hooks/useCopyToClipboard.tsx | 34 + .../src/hooks/useThemeCustomization.tsx | 16 + src/frontend/apps/calendars/src/pages/401.tsx | 19 + src/frontend/apps/calendars/src/pages/403.tsx | 21 + .../apps/calendars/src/pages/_app.tsx | 153 + .../apps/calendars/src/pages/_document.tsx | 13 + .../apps/calendars/src/pages/calendar.scss | 43 + .../apps/calendars/src/pages/calendar.tsx | 115 + .../apps/calendars/src/pages/index.scss | 128 + .../apps/calendars/src/pages/index.tsx | 132 + .../src/styles/cunningham-tokens-sass.scss | 1981 ++++ .../src/styles/cunningham-tokens.css | 1603 ++++ .../calendars/src/styles/cunningham-tokens.ts | 1 + .../apps/calendars/src/styles/globals.scss | 83 + .../apps/calendars/src/utils/useLayout.tsx | 6 + .../apps/calendars/src/utils/useQueries.ts | 12 + src/frontend/apps/calendars/svg.d.ts | 30 + src/frontend/apps/calendars/tsconfig.json | 22 + src/frontend/apps/e2e/.gitignore | 10 + src/frontend/apps/e2e/package.json | 18 + src/frontend/apps/e2e/playwright.config.ts | 79 + src/frontend/apps/e2e/tsconfig.json | 19 + src/frontend/package.json | 24 + .../packages/open-calendar/.editorconfig | 25 + .../packages/open-calendar/.gitignore | 26 + src/frontend/packages/open-calendar/LICENSE | 21 + src/frontend/packages/open-calendar/README.md | 97 + .../packages/open-calendar/doc/API.md | 16 + .../Interfacing-with-CalDAV-and-CardDAV.md | 82 + .../open-calendar/doc/User-Interface.md | 30 + .../packages/open-calendar/eslint.config.mjs | 33 + .../open-calendar/images/open-calendar.png | Bin 0 -> 116262 bytes .../packages/open-calendar/index.html | 91 + .../packages/open-calendar/package.json | 69 + .../open-calendar/src/VCardComponent.ts | 43 + .../open-calendar/src/calendarClient.ts | 282 + .../src/calendarelement/calendarElement.css | 7 + .../src/calendarelement/calendarElement.ts | 535 ++ .../calendarSelectDropdown.css | 39 + .../calendarSelectDropdown.ts | 51 + .../packages/open-calendar/src/constants.ts | 7 + .../packages/open-calendar/src/contants.ts | 25 + .../open-calendar/src/eventBody/eventBody.css | 143 + .../open-calendar/src/eventBody/eventBody.ts | 203 + .../src/eventeditpopup/eventEditPopup.css | 30 + .../src/eventeditpopup/eventEditPopup.ts | 464 + .../src/eventeditpopup/recurringEventPopup.ts | 49 + .../open-calendar/src/helpers/dav-helper.ts | 273 + .../open-calendar/src/helpers/dom-helper.ts | 11 + .../open-calendar/src/helpers/ics-helper.ts | 56 + .../open-calendar/src/helpers/types-helper.ts | 22 + .../packages/open-calendar/src/index.css | 50 + .../packages/open-calendar/src/index.ts | 23 + .../open-calendar/src/popup/popup.css | 24 + .../packages/open-calendar/src/popup/popup.ts | 35 + .../open-calendar/src/translations.ts | 123 + .../open-calendar/src/types/addressbook.ts | 30 + .../open-calendar/src/types/calendar.ts | 39 + .../open-calendar/src/types/options.ts | 160 + .../packages/open-calendar/src/vite-env.d.ts | 1 + .../packages/open-calendar/tsconfig.json | 36 + .../packages/open-calendar/vite.config.ts | 23 + .../packages/open-calendar/webpack.config.js | 43 + src/frontend/packages/open-calendar/yarn.lock | 3636 +++++++ src/frontend/yarn.lock | 8473 +++++++++++++++++ src/nginx/servers.conf.erb | 54 + 298 files changed, 41036 insertions(+) create mode 100644 .cursor/rules/django-python.mdc create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/Support_question.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/calendars-frontend.yml create mode 100644 .github/workflows/calendars.yml create mode 100644 .github/workflows/crowdin_download.yml create mode 100644 .github/workflows/crowdin_upload.yml create mode 100644 .github/workflows/docker-hub.yml create mode 100644 .github/workflows/front-dependencies-installation.yml create mode 100644 .gitignore create mode 100644 .gitlint create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 Procfile create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 bin/_config.sh create mode 100644 bin/clear_db_e2e.sql create mode 100755 bin/compose create mode 100755 bin/fernetkey create mode 100755 bin/manage create mode 100755 bin/postgres_e2e create mode 100755 bin/pylint create mode 100755 bin/pytest create mode 100644 bin/scalingo_postcompile create mode 100644 bin/scalingo_postfrontend create mode 100644 bin/scalingo_run_web create mode 100755 bin/update_app_cacert.sh create mode 100755 bin/update_openapi_schema create mode 100644 compose.yaml create mode 100644 cron.json create mode 100644 docker/auth/realm.json create mode 100644 docker/davical/Dockerfile create mode 100644 docker/davical/config.php create mode 100644 docker/davical/davical.conf create mode 100755 docker/davical/run-migrations create mode 100644 docker/files/development/etc/nginx/conf.d/default.conf create mode 100644 docker/files/docker-entrypoint-initdb.d/init-databases.sh create mode 100644 docker/files/etc/nginx/conf.d/default.conf create mode 100755 docker/postgresql/init-databases.sh create mode 100644 docs/architecture.md create mode 100644 env.d/development/backend.defaults create mode 100644 env.d/development/crowdin.defaults create mode 100644 env.d/development/davical.defaults create mode 100644 env.d/development/frontend.defaults create mode 100644 env.d/development/keycloak.defaults create mode 100644 env.d/development/postgresql.defaults create mode 100644 env.d/development/postgresql.e2e create mode 100644 gitlint/gitlint_emoji.py create mode 100644 renovate.json create mode 100644 src/backend/.dockerignore create mode 100644 src/backend/.pylintrc create mode 100644 src/backend/Dockerfile create mode 100644 src/backend/MANIFEST.in create mode 100644 src/backend/__init__.py create mode 100644 src/backend/calendars/__init__.py create mode 100644 src/backend/calendars/celery_app.py create mode 100644 src/backend/calendars/configuration/theme/default.json create mode 100755 src/backend/calendars/settings.py create mode 100644 src/backend/calendars/urls.py create mode 100644 src/backend/calendars/wsgi.py create mode 100644 src/backend/core/__init__.py create mode 100644 src/backend/core/admin.py create mode 100644 src/backend/core/api/__init__.py create mode 100644 src/backend/core/api/fields.py create mode 100644 src/backend/core/api/permissions.py create mode 100644 src/backend/core/api/serializers.py create mode 100644 src/backend/core/api/viewsets.py create mode 100644 src/backend/core/api/viewsets_caldav.py create mode 100644 src/backend/core/apps.py create mode 100644 src/backend/core/authentication/__init__.py create mode 100644 src/backend/core/authentication/backends.py create mode 100644 src/backend/core/authentication/exceptions.py create mode 100644 src/backend/core/authentication/views.py create mode 100644 src/backend/core/enums.py create mode 100644 src/backend/core/external_api/permissions.py create mode 100644 src/backend/core/external_api/viewsets.py create mode 100644 src/backend/core/factories.py create mode 100644 src/backend/core/management/commands/__init__.py create mode 100644 src/backend/core/management/commands/createsuperuser.py create mode 100644 src/backend/core/migrations/0001_initial.py create mode 100644 src/backend/core/migrations/__init__.py create mode 100644 src/backend/core/models.py create mode 100644 src/backend/core/services/__init__.py create mode 100644 src/backend/core/services/caldav_service.py create mode 100644 src/backend/core/signals.py create mode 100644 src/backend/core/templatetags/__init__.py create mode 100644 src/backend/core/templatetags/extra_tags.py create mode 100644 src/backend/core/tests/__init__.py create mode 100644 src/backend/core/tests/authentication/__init__.py create mode 100644 src/backend/core/tests/authentication/test_backends.py create mode 100644 src/backend/core/tests/authentication/test_views.py create mode 100644 src/backend/core/tests/conftest.py create mode 100644 src/backend/core/tests/external_api/test_external_api_users.py create mode 100644 src/backend/core/tests/swagger/__init__.py create mode 100644 src/backend/core/tests/swagger/test_openapi_schema.py create mode 100644 src/backend/core/tests/test_api_config.py create mode 100644 src/backend/core/tests/test_api_users.py create mode 100644 src/backend/core/tests/test_caldav_service.py create mode 100644 src/backend/core/tests/test_models_users.py create mode 100644 src/backend/core/tests/test_settings.py create mode 100644 src/backend/core/tests/utils/urls.py create mode 100644 src/backend/core/urls.py create mode 100644 src/backend/e2e/__init__.py create mode 100644 src/backend/e2e/management/commands/__init__.py create mode 100644 src/backend/e2e/serializers.py create mode 100644 src/backend/e2e/tests/test_api_e2e.py create mode 100644 src/backend/e2e/urls.py create mode 100644 src/backend/e2e/utils.py create mode 100644 src/backend/e2e/viewsets.py create mode 100755 src/backend/entrypoint create mode 100644 src/backend/gunicorn.conf.py create mode 100644 src/backend/locale/de_DE/LC_MESSAGES/django.po create mode 100644 src/backend/locale/en_US/LC_MESSAGES/django.po create mode 100644 src/backend/locale/fr_FR/LC_MESSAGES/django.po create mode 100644 src/backend/locale/nl_NL/LC_MESSAGES/django.po create mode 100644 src/backend/manage.py create mode 100644 src/backend/pyproject.toml create mode 100644 src/backend/uv.lock create mode 100644 src/frontend/.dockerignore create mode 100644 src/frontend/Dockerfile create mode 100644 src/frontend/apps/calendars/.env create mode 100644 src/frontend/apps/calendars/.env.development create mode 100644 src/frontend/apps/calendars/.gitignore create mode 100644 src/frontend/apps/calendars/README.md create mode 100644 src/frontend/apps/calendars/__mocks__/fileMock.js create mode 100644 src/frontend/apps/calendars/conf/default.conf create mode 100644 src/frontend/apps/calendars/cunningham.ts create mode 100644 src/frontend/apps/calendars/eslint.config.mjs create mode 100644 src/frontend/apps/calendars/jest.config.ts create mode 100644 src/frontend/apps/calendars/next.config.ts create mode 100644 src/frontend/apps/calendars/package.json create mode 100644 src/frontend/apps/calendars/public/assets/401-background.png create mode 100644 src/frontend/apps/calendars/public/assets/403-background.png create mode 100644 src/frontend/apps/calendars/public/assets/anct_favicon.png create mode 100644 src/frontend/apps/calendars/public/assets/anct_logo-icon.svg create mode 100644 src/frontend/apps/calendars/public/assets/anct_logo_alpha.svg create mode 100644 src/frontend/apps/calendars/public/assets/anct_logo_beta.svg create mode 100644 src/frontend/apps/calendars/public/assets/favicon.png create mode 100644 src/frontend/apps/calendars/public/assets/logo-icon_alpha.svg create mode 100644 src/frontend/apps/calendars/public/assets/logo-icon_beta.svg create mode 100644 src/frontend/apps/calendars/public/assets/logo-suite-numerique.png create mode 100644 src/frontend/apps/calendars/public/assets/logo_alpha.svg create mode 100644 src/frontend/apps/calendars/public/mime-video.svg create mode 100644 src/frontend/apps/calendars/src/assets/feedback/form.svg create mode 100644 src/frontend/apps/calendars/src/assets/feedback/tchap.svg create mode 100644 src/frontend/apps/calendars/src/assets/feedback/visio.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/cancel.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/cancel_blue.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/delete_filled.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/info.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/settings.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/trash.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/undo.svg create mode 100644 src/frontend/apps/calendars/src/assets/icons/undo_blue.svg create mode 100644 src/frontend/apps/calendars/src/assets/logo-gouv.svg create mode 100644 src/frontend/apps/calendars/src/assets/logo-icon.svg create mode 100644 src/frontend/apps/calendars/src/features/analytics/AnalyticsProvider.tsx create mode 100644 src/frontend/apps/calendars/src/features/api/APIError.ts create mode 100644 src/frontend/apps/calendars/src/features/api/fetchApi.ts create mode 100644 src/frontend/apps/calendars/src/features/api/types.ts create mode 100644 src/frontend/apps/calendars/src/features/api/utils.ts create mode 100644 src/frontend/apps/calendars/src/features/auth/Auth.tsx create mode 100644 src/frontend/apps/calendars/src/features/auth/components/LoginButton.tsx create mode 100644 src/frontend/apps/calendars/src/features/auth/components/LogoutButton.tsx create mode 100644 src/frontend/apps/calendars/src/features/auth/types.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/api.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/CalendarList.scss create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/CalendarList.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/CalendarView.scss create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/CalendarView.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/CreateCalendarModal.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/EventModal.scss create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/EventModal.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/EventModalAdapter.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/LeftPanel.scss create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/LeftPanel.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/MiniCalendar.scss create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/MiniCalendar.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/RecurrenceEditor.scss create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/RecurrenceEditor.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/components/index.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/hooks/useCalendars.ts create mode 100644 src/frontend/apps/calendars/src/features/calendar/hooks/useCreateEventModal.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/hooks/useEventModal.tsx create mode 100644 src/frontend/apps/calendars/src/features/calendar/types.ts create mode 100644 src/frontend/apps/calendars/src/features/config/Config.ts create mode 100644 src/frontend/apps/calendars/src/features/config/ConfigProvider.tsx create mode 100644 src/frontend/apps/calendars/src/features/config/useApiConfig.ts create mode 100644 src/frontend/apps/calendars/src/features/errors/AppError.ts create mode 100644 src/frontend/apps/calendars/src/features/feedback/Feedback.scss create mode 100644 src/frontend/apps/calendars/src/features/feedback/Feedback.tsx create mode 100644 src/frontend/apps/calendars/src/features/feedback/useMessagesWidget.tsx create mode 100644 src/frontend/apps/calendars/src/features/forms/components/RhfInput.tsx create mode 100644 src/frontend/apps/calendars/src/features/i18n/conf.ts create mode 100644 src/frontend/apps/calendars/src/features/i18n/initI18n.ts create mode 100644 src/frontend/apps/calendars/src/features/i18n/translations.json create mode 100644 src/frontend/apps/calendars/src/features/i18n/utils.ts create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/global/GlobalLayout.scss create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/global/GlobalLayout.tsx create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/header/Header.tsx create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/header/index.scss create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/left-panel/LeftPanelMobile.scss create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/left-panel/LeftPanelMobile.tsx create mode 100644 src/frontend/apps/calendars/src/features/layouts/components/simple/SimpleLayout.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/breadcrumbs/Breadcrumbs.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/breadcrumbs/index.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/circular-progress/CircularProgress.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/gaufre/Gaufre.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/generic-disclaimer/GenericDisclaimer.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/generic-disclaimer/GenericDisclaimer.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/icon/Icon.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/infinite-scroll/InfiniteScroll.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/infinite-scroll/InfiniteScroll.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/infinite-scroll/index.ts create mode 100644 src/frontend/apps/calendars/src/features/ui/components/info/InfoRow.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/info/InfoRow.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/responsive/ResponsiveDivs.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/responsive/index.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/spinner/SpinnerPage.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/spinner/SpinnerPage.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/toaster/Toaster.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/components/toaster/index.scss create mode 100644 src/frontend/apps/calendars/src/features/ui/components/user/UserProfile.tsx create mode 100644 src/frontend/apps/calendars/src/features/ui/cunningham/useCunninghamTheme.ts create mode 100644 src/frontend/apps/calendars/src/features/users/hooks/useUserQueries.tsx create mode 100644 src/frontend/apps/calendars/src/features/users/types.ts create mode 100644 src/frontend/apps/calendars/src/hooks/useCopyToClipboard.tsx create mode 100644 src/frontend/apps/calendars/src/hooks/useThemeCustomization.tsx create mode 100644 src/frontend/apps/calendars/src/pages/401.tsx create mode 100644 src/frontend/apps/calendars/src/pages/403.tsx create mode 100644 src/frontend/apps/calendars/src/pages/_app.tsx create mode 100644 src/frontend/apps/calendars/src/pages/_document.tsx create mode 100644 src/frontend/apps/calendars/src/pages/calendar.scss create mode 100644 src/frontend/apps/calendars/src/pages/calendar.tsx create mode 100644 src/frontend/apps/calendars/src/pages/index.scss create mode 100644 src/frontend/apps/calendars/src/pages/index.tsx create mode 100644 src/frontend/apps/calendars/src/styles/cunningham-tokens-sass.scss create mode 100644 src/frontend/apps/calendars/src/styles/cunningham-tokens.css create mode 100644 src/frontend/apps/calendars/src/styles/cunningham-tokens.ts create mode 100644 src/frontend/apps/calendars/src/styles/globals.scss create mode 100644 src/frontend/apps/calendars/src/utils/useLayout.tsx create mode 100644 src/frontend/apps/calendars/src/utils/useQueries.ts create mode 100644 src/frontend/apps/calendars/svg.d.ts create mode 100644 src/frontend/apps/calendars/tsconfig.json create mode 100644 src/frontend/apps/e2e/.gitignore create mode 100644 src/frontend/apps/e2e/package.json create mode 100644 src/frontend/apps/e2e/playwright.config.ts create mode 100644 src/frontend/apps/e2e/tsconfig.json create mode 100644 src/frontend/package.json create mode 100644 src/frontend/packages/open-calendar/.editorconfig create mode 100644 src/frontend/packages/open-calendar/.gitignore create mode 100644 src/frontend/packages/open-calendar/LICENSE create mode 100644 src/frontend/packages/open-calendar/README.md create mode 100644 src/frontend/packages/open-calendar/doc/API.md create mode 100644 src/frontend/packages/open-calendar/doc/Interfacing-with-CalDAV-and-CardDAV.md create mode 100644 src/frontend/packages/open-calendar/doc/User-Interface.md create mode 100644 src/frontend/packages/open-calendar/eslint.config.mjs create mode 100644 src/frontend/packages/open-calendar/images/open-calendar.png create mode 100644 src/frontend/packages/open-calendar/index.html create mode 100644 src/frontend/packages/open-calendar/package.json create mode 100644 src/frontend/packages/open-calendar/src/VCardComponent.ts create mode 100644 src/frontend/packages/open-calendar/src/calendarClient.ts create mode 100644 src/frontend/packages/open-calendar/src/calendarelement/calendarElement.css create mode 100644 src/frontend/packages/open-calendar/src/calendarelement/calendarElement.ts create mode 100644 src/frontend/packages/open-calendar/src/calendarselectdropdown/calendarSelectDropdown.css create mode 100644 src/frontend/packages/open-calendar/src/calendarselectdropdown/calendarSelectDropdown.ts create mode 100644 src/frontend/packages/open-calendar/src/constants.ts create mode 100644 src/frontend/packages/open-calendar/src/contants.ts create mode 100644 src/frontend/packages/open-calendar/src/eventBody/eventBody.css create mode 100644 src/frontend/packages/open-calendar/src/eventBody/eventBody.ts create mode 100644 src/frontend/packages/open-calendar/src/eventeditpopup/eventEditPopup.css create mode 100644 src/frontend/packages/open-calendar/src/eventeditpopup/eventEditPopup.ts create mode 100644 src/frontend/packages/open-calendar/src/eventeditpopup/recurringEventPopup.ts create mode 100644 src/frontend/packages/open-calendar/src/helpers/dav-helper.ts create mode 100644 src/frontend/packages/open-calendar/src/helpers/dom-helper.ts create mode 100644 src/frontend/packages/open-calendar/src/helpers/ics-helper.ts create mode 100644 src/frontend/packages/open-calendar/src/helpers/types-helper.ts create mode 100644 src/frontend/packages/open-calendar/src/index.css create mode 100644 src/frontend/packages/open-calendar/src/index.ts create mode 100644 src/frontend/packages/open-calendar/src/popup/popup.css create mode 100644 src/frontend/packages/open-calendar/src/popup/popup.ts create mode 100644 src/frontend/packages/open-calendar/src/translations.ts create mode 100644 src/frontend/packages/open-calendar/src/types/addressbook.ts create mode 100644 src/frontend/packages/open-calendar/src/types/calendar.ts create mode 100644 src/frontend/packages/open-calendar/src/types/options.ts create mode 100644 src/frontend/packages/open-calendar/src/vite-env.d.ts create mode 100644 src/frontend/packages/open-calendar/tsconfig.json create mode 100644 src/frontend/packages/open-calendar/vite.config.ts create mode 100644 src/frontend/packages/open-calendar/webpack.config.js create mode 100644 src/frontend/packages/open-calendar/yarn.lock create mode 100644 src/frontend/yarn.lock create mode 100644 src/nginx/servers.conf.erb diff --git a/.cursor/rules/django-python.mdc b/.cursor/rules/django-python.mdc new file mode 100644 index 0000000..0270cbc --- /dev/null +++ b/.cursor/rules/django-python.mdc @@ -0,0 +1,77 @@ +--- +description: Rules for writing Python with Django +globs: src/backend/**/*.py +alwaysApply: false +--- +You are an expert in Python, Django, and scalable web application development. + +Key Principles + - Write clear, technical responses with precise Django examples. + - Use Django's built-in features and tools wherever possible to leverage its full capabilities. + - Prioritize readability and maintainability; follow Django's coding style guide (PEP 8 compliance for the most part, with the one exception being 100 characters per line instead of 79). + - Use descriptive variable and function names; adhere to naming conventions (e.g., lowercase with underscores for functions and variables). + +Django/Python + - Use Django REST Framework viewsets for API endpoints. + - Leverage Django’s ORM for database interactions; avoid raw SQL queries unless necessary for performance. + - Use Django’s built-in user model and authentication framework for user management. + - Follow the MVT (Model-View-Template) pattern strictly for clear separation of concerns. + - Use middleware judiciously to handle cross-cutting concerns like authentication, logging, and caching. + +Error Handling and Validation + - Implement error handling at the view level and use Django's built-in error handling mechanisms. + - Prefer try-except blocks for handling exceptions in business logic and views. + +Dependencies + - Django + - Django REST Framework (for API development) + - Celery (for background tasks) + - Redis (for caching and task queues) + - PostgreSQL (preferred databases for production) + - Minio (file storage for production) + - OIDC prodiver (for managing authentication) + +Django-Specific Guidelines + - Use Django templates for rendering HTML and DRF serializers for JSON responses. + - Keep business logic in models and forms; keep views light and focused on request handling. + - Use Django's URL dispatcher (urls.py) to define clear and RESTful URL patterns. + - Apply Django's security best practices (e.g., CSRF protection, SQL injection protection, XSS prevention). + - Use Django’s built-in tools for testing (pytest-django) to ensure code quality and reliability. + - Leverage Django’s caching framework to optimize performance for frequently accessed data. + - Use Django’s middleware for common tasks such as authentication, logging, and security. + +Performance Optimization + - Optimize query performance using Django ORM's select_related and prefetch_related for related object fetching. + - Use Django’s cache framework with backend support (e.g., Redis or Memcached) to reduce database load. + - Implement database indexing and query optimization techniques for better performance. + - Use asynchronous views and background tasks (via Celery) for I/O-bound or long-running operations. + - Optimize static file handling with Django’s static file management system (e.g., WhiteNoise). + +Logging + - As a general rule, we should have logs for every expected and unexpected actions of the application, using the appropriate log level. + - We should also be logging these exceptions to Sentry with the Sentry Python SDK. Python exceptions should almost always be captured automatically without extra instrumentation, but custom ones (such as failed requests to external services, query errors, or Celery task failures) can be tracked using capture_exception(). + +Log Levels + - A log level or log severity is a piece of information telling how important a given log message is: + - DEBUG: should be used for information that may be needed for diagnosing issues and troubleshooting or when running application in the test environment for the purpose of making sure everything is running correctly + - INFO: should be used as standard log level, indicating that something happened + - WARN: should be used when something unexpected happened but the code can continue the work + - ERROR: should be used when the application hits an issue preventing one or more functionalities from properly functioning + +Security + - Don’t log sensitive information. Make sure you never log: + - authorization tokens + - passwords + - financial data + - health data + - PII (Personal Identifiable Information) + +Testing + - All new packages and most new significant functionality should come with unit tests + +Unit tests + - A good unit test should: + - focus on a single use-case at a time + - have a minimal set of assertions per test + - demonstrate every use case. The rule of thumb is: if it can happen, it should be covered +Refer to Django documentation for best practices in views, models, forms, and security considerations. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..24e79d0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,6 @@ + diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 0000000..53aba2e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,28 @@ +--- +name: 🐛 Bug Report +about: If something is not working as expected 🤔. + +--- + +## Bug Report + +**Problematic behavior** +A clear and concise description of the behavior. + +**Expected behavior/code** +A clear and concise description of what you expected to happen (or code). + +**Steps to Reproduce** +1. Do this... +2. Then this... +3. And then the bug happens! + +**Environment** +- Calendars version: +- Platform: + +**Possible Solution** + + +**Additional context/Screenshots** +Add any other context about the problem here. If applicable, add screenshots to help explain. diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 0000000..51d3170 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,23 @@ +--- +name: ✨ Feature Request +about: I have a suggestion (and may want to build it 💪)! + +--- + +## Feature Request + +**Is your feature request related to a problem or unsupported use case? Please describe.** +A clear and concise description of what the problem is. For example: I need to do some task and I have an issue... + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. Add any considered drawbacks. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Discovery, Documentation, Adoption, Migration Strategy** +If you can, explain how users will be able to use this and possibly write out a version the docs (if applicable). +Maybe a screenshot or design? + +**Do you want to work on it through a Pull Request?** + diff --git a/.github/ISSUE_TEMPLATE/Support_question.md b/.github/ISSUE_TEMPLATE/Support_question.md new file mode 100644 index 0000000..d73b0fc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Support_question.md @@ -0,0 +1,22 @@ +--- +name: 🤗 Support Question +about: If you have a question 💬, or something was not clear from the docs! + +--- + + + +--- + +Please make sure you have read our [main Readme](https://github.com/suitenumerique/calendars). + +Also make sure it was not already answered in [an open or close issue](https://github.com/suitenumerique/calendars/issues). + +If your question was not covered, and you feel like it should be, fire away! We'd love to improve our docs! 👌 + +**Topic** +What's the general area of your question: for example, docker setup, database schema, search functionality,... + +**Question** +Try to be as specific as possible so we can help you as best we can. Please be patient 🙏 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..85cfbe6 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ +## Purpose + +Description... + + +## Proposal + +Description... + +- [] item 1... +- [] item 2... diff --git a/.github/workflows/calendars-frontend.yml b/.github/workflows/calendars-frontend.yml new file mode 100644 index 0000000..317473e --- /dev/null +++ b/.github/workflows/calendars-frontend.yml @@ -0,0 +1,114 @@ +name: Frontend Workflow + +on: + push: + branches: + - main + pull_request: + branches: + - "*" + +jobs: + install-front: + uses: ./.github/workflows/front-dependencies-installation.yml + with: + node_version: "22.x" + + lint-front: + runs-on: ubuntu-latest + needs: install-front + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22.x" + - name: Restore the frontend cache + uses: actions/cache@v4 + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} + fail-on-cache-miss: true + + - name: Check linting + run: cd src/frontend/ && yarn lint + + test-unit: + runs-on: ubuntu-latest + needs: install-front + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22.x" + + - name: Restore the frontend cache + uses: actions/cache@v4 + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} + fail-on-cache-miss: true + + - name: Run unit tests + run: | + cd src/frontend/apps/calendars + yarn test + + test-e2e: + runs-on: ubuntu-latest + needs: install-front + strategy: + matrix: + browser: + - chromium + - webkit + - firefox + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22.x" + + - name: Restore the frontend cache + uses: actions/cache@v4 + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} + fail-on-cache-miss: true + + - name: Install Playwright Browsers + run: | + cd src/frontend/apps/e2e + npx playwright install --with-deps ${{matrix.browser}} + + - name: Start Docker services + run: | + make bootstrap-e2e + + - name: Start frontend + run: | + cd src/frontend && yarn dev & + + - name: Wait for Keycloak to be ready + run: | + timeout 30 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:8083/)" != "302" ]]; do echo "Waiting for Keycloak..." && sleep 2; done' && echo "Keycloak is ready!" + + - name: Run e2e tests + run: | + cd src/frontend/apps/e2e + yarn test --project=${{ matrix.browser }} + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: report-${{ matrix.browser }} + path: src/frontend/apps/e2e/report/ + retention-days: 7 diff --git a/.github/workflows/calendars.yml b/.github/workflows/calendars.yml new file mode 100644 index 0000000..9de8b6e --- /dev/null +++ b/.github/workflows/calendars.yml @@ -0,0 +1,187 @@ +name: Main Workflow + +on: + push: + branches: + - main + pull_request: + branches: + - "*" + +jobs: + lint-git: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' # Makes sense only for pull requests + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: show + run: git log + - name: Enforce absence of print statements in code + if: always() + run: | + ! git diff origin/${{ github.event.pull_request.base.ref }}..HEAD -- . ':(exclude)**/calendars.yml' | grep "print(" + - name: Check absence of fixup commits + if: always() + run: | + ! git log | grep 'fixup!' + - name: Install gitlint + if: always() + run: pip install --user requests gitlint + - name: Lint commit messages added to main + if: always() + run: ~/.local/bin/gitlint --commits origin/${{ github.event.pull_request.base.ref }}..HEAD + + check-changelog: + runs-on: ubuntu-latest + if: | + contains(github.event.pull_request.labels.*.name, 'noChangeLog') == false && + github.event_name == 'pull_request' + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 50 + - name: Check that the CHANGELOG has been modified in the current branch + run: git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.after }} | grep 'CHANGELOG.md' + + lint-changelog: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: Check CHANGELOG max line length + run: | + max_line_length=$(cat CHANGELOG.md | grep -Ev "^\[.*\]: https://github.com" | wc -L) + if [ $max_line_length -ge 80 ]; then + echo "ERROR: CHANGELOG has lines longer than 80 characters." + exit 1 + fi + + lint-back: + runs-on: ubuntu-latest + defaults: + run: + working-directory: src/backend + steps: + - name: Checkout repository + uses: actions/checkout@v6 + - name: "Set up Python" + uses: actions/setup-python@v6 + with: + python-version-file: "src/backend/pyproject.toml" + - name: Install uv + uses: astral-sh/setup-uv@v6 + - name: Install the project + run: uv sync --locked --all-extras + + - name: Check code formatting with ruff + run: uv run ruff format . --diff + - name: Lint code with ruff + run: uv run ruff check . + - name: Lint code with pylint + run: uv run pylint . + + test-back: + runs-on: ubuntu-latest + needs: build-mails + + defaults: + run: + working-directory: src/backend + + services: + postgres: + image: postgres:16 + env: + POSTGRES_DB: calendars + POSTGRES_USER: pgroot + POSTGRES_PASSWORD: pass + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + + env: + DJANGO_CONFIGURATION: Test + DJANGO_SETTINGS_MODULE: calendars.settings + DJANGO_SECRET_KEY: ThisIsAnExampleKeyForTestPurposeOnly + OIDC_OP_JWKS_ENDPOINT: /endpoint-for-test-purpose-only + DJANGO_EMAIL_HOST: mailcatcher + DB_HOST: localhost + DB_NAME: calendars + DB_USER: pgroot + DB_PASSWORD: pass + DB_PORT: 5432 + STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage + AWS_S3_ENDPOINT_URL: http://localhost:9000 + AWS_S3_ACCESS_KEY_ID: calendar + AWS_S3_SECRET_ACCESS_KEY: password + MEDIA_BASE_URL: http://localhost:8083 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Create writable /data + run: | + sudo mkdir -p /data/media && \ + sudo mkdir -p /data/static + + - name: Restore the mail templates + uses: actions/cache@v4 + id: mail-templates + with: + path: "src/backend/core/templates/mail" + key: mail-templates-${{ hashFiles('src/mail/mjml') }} + + - name: Start MinIO + run: | + docker pull minio/minio + docker run -d --name minio \ + -p 9000:9000 \ + -e "MINIO_ACCESS_KEY=calendar" \ + -e "MINIO_SECRET_KEY=password" \ + -v /data/media:/data \ + minio/minio server --console-address :9001 /data + + # Tool to wait for a service to be ready + - name: Install Dockerize + run: | + curl -sSL https://github.com/jwilder/dockerize/releases/download/v0.8.0/dockerize-linux-amd64-v0.8.0.tar.gz | sudo tar -C /usr/local/bin -xzv + + - name: Wait for MinIO to be ready + run: | + dockerize -wait tcp://localhost:9000 -timeout 10s + + - name: Configure MinIO + run: | + MINIO=$(docker ps | grep minio/minio | sed -E 's/.*\s+([a-zA-Z0-9_-]+)$/\1/') + docker exec ${MINIO} sh -c \ + "mc alias set calendar http://localhost:9000 calendar password && \ + mc alias ls && \ + mc mb calendar/calendar-media-storage && \ + mc version enable calendar/calendar-media-storage" + + - name: "Set up Python" + uses: actions/setup-python@v6 + with: + python-version-file: "src/backend/pyproject.toml" + - name: Install uv + uses: astral-sh/setup-uv@v6 + - name: Install the dependencies + run: uv sync --locked --all-extras + + - name: Install gettext (required to compile messages) and MIME support + run: | + sudo apt-get update + sudo apt-get install -y gettext pandoc shared-mime-info + sudo wget https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types -O /etc/mime.types + + - name: Generate a MO file from strings extracted from the project + run: uv run python manage.py compilemessages + + - name: Run tests + run: uv run pytest -n 2 diff --git a/.github/workflows/crowdin_download.yml b/.github/workflows/crowdin_download.yml new file mode 100644 index 0000000..aa9d657 --- /dev/null +++ b/.github/workflows/crowdin_download.yml @@ -0,0 +1,76 @@ +name: Download translations from Crowdin + +on: + workflow_dispatch: + push: + branches: + - 'release/**' + +jobs: + install-front: + uses: ./.github/workflows/front-dependencies-installation.yml + with: + node_version: '20.x' + + synchronize-with-crowdin: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Create empty source files + run: | + touch src/backend/locale/django.pot + mkdir -p src/frontend/packages/i18n/locales/impress/ + touch src/frontend/packages/i18n/locales/impress/translations-crowdin.json + # crowdin workflow + - name: crowdin action + uses: crowdin/github-action@v2 + with: + config: crowdin/config.yml + upload_sources: false + upload_translations: false + download_translations: true + create_pull_request: false + push_translations: false + push_sources: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # A numeric ID, found at https://crowdin.com/project//tools/api + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + + # Visit https://crowdin.com/settings#api-key to create this token + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + + CROWDIN_BASE_PATH: "../src/" + # frontend i18n + - name: Restore the frontend cache + uses: actions/cache@v4 + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} + fail-on-cache-miss: true + - name: generate translations files + working-directory: src/frontend + run: yarn i18n:deploy + # Create a new PR + - name: Create a new Pull Request with new translated strings + uses: peter-evans/create-pull-request@v7 + with: + commit-message: | + 🌐(i18n) update translated strings + + Update translated files with new translations + title: 🌐(i18n) update translated strings + body: | + ## Purpose + + update translated strings + + ## Proposal + + - [x] update translated strings + branch: i18n/update-translations + labels: i18n diff --git a/.github/workflows/crowdin_upload.yml b/.github/workflows/crowdin_upload.yml new file mode 100644 index 0000000..000ecca --- /dev/null +++ b/.github/workflows/crowdin_upload.yml @@ -0,0 +1,68 @@ +name: Update crowdin sources + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + install-front: + uses: ./.github/workflows/front-dependencies-installation.yml + with: + node_version: '20.x' + + synchronize-with-crowdin: + needs: install-front + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + # Backend i18n + - name: Install Python + uses: actions/setup-python@v6 + with: + python-version: "3.13.9" + cache: 'pip' + - name: Upgrade pip and setuptools + run: pip install --upgrade pip setuptools + - name: Install development dependencies + run: pip install --user . + working-directory: src/backend + - name: Install gettext + run: | + sudo apt-get update + sudo apt-get install -y gettext pandoc + - name: generate pot files + working-directory: src/backend + run: | + DJANGO_CONFIGURATION=Build python manage.py makemessages -a --keep-pot + # frontend i18n + - name: Restore the frontend cache + uses: actions/cache@v4 + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} + fail-on-cache-miss: true + - name: generate source translation file + working-directory: src/frontend + run: yarn i18n:extract + # crowdin workflow + - name: crowdin action + uses: crowdin/github-action@v2 + with: + config: crowdin/config.yml + upload_sources: true + upload_translations: false + download_translations: false + create_pull_request: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # A numeric ID, found at https://crowdin.com/project//tools/api + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + + # Visit https://crowdin.com/settings#api-key to create this token + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + + CROWDIN_BASE_PATH: "../src/" diff --git a/.github/workflows/docker-hub.yml b/.github/workflows/docker-hub.yml new file mode 100644 index 0000000..dc55946 --- /dev/null +++ b/.github/workflows/docker-hub.yml @@ -0,0 +1,104 @@ +name: Docker Hub Workflow +run-name: Docker Hub Workflow + +on: + workflow_dispatch: + push: + branches: + - 'main' + tags: + - 'v*' + pull_request: + branches: + - 'main' + +env: + DOCKER_USER: 1001:127 + +jobs: + build-and-push-backend: + runs-on: ubuntu-latest + steps: + - + name: Checkout repository + uses: actions/checkout@v6 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: lasuite/calendars-backend + - + name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + - + name: Run trivy scan + uses: numerique-gouv/action-trivy-cache@main + with: + docker-build-args: '--target backend-production -f Dockerfile' + docker-image-name: 'docker.io/lasuite/calendars-backend:${{ github.sha }}' + - + name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + target: backend-production + build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + build-and-push-frontend: + runs-on: ubuntu-latest + steps: + - + name: Checkout repository + uses: actions/checkout@v6 + - + name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: lasuite/calendars-frontend + - + name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + - + name: Run trivy scan + uses: numerique-gouv/action-trivy-cache@main + with: + docker-build-args: '-f src/frontend/Dockerfile --target frontend-production' + docker-image-name: 'docker.io/lasuite/calendars-frontend:${{ github.sha }}' + - + name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + file: ./src/frontend/Dockerfile + target: frontend-production + build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + notify-argocd: + needs: + - build-and-push-frontend + - build-and-push-backend + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + steps: + - uses: numerique-gouv/action-argocd-webhook-notification@main + id: notify + with: + deployment_repo_path: "${{ secrets.DEPLOYMENT_REPO_URL }}" + argocd_webhook_secret: "${{ secrets.ARGOCD_PREPROD_WEBHOOK_SECRET }}" + argocd_url: "${{ vars.ARGOCD_PREPROD_WEBHOOK_URL }}" diff --git a/.github/workflows/front-dependencies-installation.yml b/.github/workflows/front-dependencies-installation.yml new file mode 100644 index 0000000..f95153d --- /dev/null +++ b/.github/workflows/front-dependencies-installation.yml @@ -0,0 +1,36 @@ +name: Install frontend installation reusable workflow + +on: + workflow_call: + inputs: + node_version: + required: false + default: '20.x' + type: string + +jobs: + front-dependencies-installation: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Restore the frontend cache + uses: actions/cache@v4 + id: front-node_modules + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} + - name: Setup Node.js + if: steps.front-node_modules.outputs.cache-hit != 'true' + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node_version }} + - name: Install dependencies + if: steps.front-node_modules.outputs.cache-hit != 'true' + run: cd src/frontend/ && yarn install --frozen-lockfile + - name: Cache install frontend + if: steps.front-node_modules.outputs.cache-hit != 'true' + uses: actions/cache@v4 + with: + path: "src/frontend/**/node_modules" + key: front-node_modules-${{ hashFiles('src/frontend/**/yarn.lock') }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..083bf55 --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +.DS_Store +.next/ + +# Translations # Translations +*.mo +*.pot + +# Environments +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +env.d/development/*.local +env.d/terraform + +# Docker +compose.override.yml +docker/auth/*.local + +# npm +node_modules + +# Mails +src/backend/core/templates/mail/ + +# Swagger +**/swagger.json + +# Logs +*.log + +# Terraform +.terraform +*.tfstate +*.tfstate.backup + +# Test & lint +.coverage +.pylint.d +.pytest_cache +db.sqlite3 +.mypy_cache + +# Site media +/data/ + +# IDEs +.idea/ +.vscode/ +*.iml +.devcontainer + +# Various +.turbo diff --git a/.gitlint b/.gitlint new file mode 100644 index 0000000..f7373b6 --- /dev/null +++ b/.gitlint @@ -0,0 +1,78 @@ +# All these sections are optional, edit this file as you like. +[general] +# Ignore certain rules, you can reference them by their id or by their full name +# ignore=title-trailing-punctuation, T3 + +# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this +# verbosity = 2 + +# By default gitlint will ignore merge commits. Set to 'false' to disable. +# ignore-merge-commits=true + +# By default gitlint will ignore fixup commits. Set to 'false' to disable. +# ignore-fixup-commits=true + +# By default gitlint will ignore squash commits. Set to 'false' to disable. +# ignore-squash-commits=true + +# Enable debug mode (prints more output). Disabled by default. +# debug=true + +# Set the extra-path where gitlint will search for user defined rules +# See http://jorisroovers.github.io/gitlint/user_defined_rules for details +extra-path=gitlint/ + +# [title-max-length] +# line-length=80 + +[title-must-not-contain-word] +# Comma-separated list of words that should not occur in the title. Matching is case +# insensitive. It's fine if the keyword occurs as part of a larger word (so "WIPING" +# will not cause a violation, but "WIP: my title" will. +words=wip + +#[title-match-regex] +# python like regex (https://docs.python.org/2/library/re.html) that the +# commit-msg title must be matched to. +# Note that the regex can contradict with other rules if not used correctly +# (e.g. title-must-not-contain-word). +#regex= + +# [B1] +# B1 = body-max-line-length +# line-length=120 +# [body-min-length] +# min-length=5 + +# [body-is-missing] +# Whether to ignore this rule on merge commits (which typically only have a title) +# default = True +# ignore-merge-commits=false + +# [body-changed-file-mention] +# List of files that need to be explicitly mentioned in the body when they are changed +# This is useful for when developers often erroneously edit certain files or git submodules. +# By specifying this rule, developers can only change the file when they explicitly reference +# it in the commit message. +# files=gitlint/rules.py,README.md + +# [author-valid-email] +# python like regex (https://docs.python.org/2/library/re.html) that the +# commit author email address should be matched to +# For example, use the following regex if you only want to allow email addresses from foo.com +# regex=[^@]+@foo.com + +[ignore-by-title] +# Allow empty body & wrong title pattern only when bots (pyup/greenkeeper) +# upgrade dependencies +regex=^(⬆️.*|Update (.*) from (.*) to (.*)|(chore|fix)\(package\): update .*)$ +ignore=B6,UC1 + +# [ignore-by-body] +# Ignore certain rules for commits of which the body has a line that matches a regex +# E.g. Match bodies that have a line that that contain "release" +# regex=(.*)release(.*) +# +# Ignore certain rules, you can reference them by their id or by their full name +# Use 'all' to ignore all rules +# ignore=T1,body-min-length diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..56414d7 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,79 @@ +# Contributor Covenant Code of Conduct +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +- Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. +- Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +- This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +- Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at contact@suite.anct.gouv.fr. + +- All complaints will be reviewed and investigated promptly and fairly. + +- All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +- Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of the following Code of Conduct + +## Code of Conduct: + +### 1. Correction + +Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +Community Impact: A violation through a single incident or series of actions. + +Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +Community Impact: A serious violation of community standards, including sustained inappropriate behavior. + +Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +Consequence: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. + +Community Impact Guidelines were inspired by Mozilla's [code of conduct enforcement ladder](https://github.com/mozilla/inclusion/blob/master/code-of-conduct-enforcement/consequence-ladder.md). + +For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d1ed138 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,84 @@ +# Contributing to the Project + +Thank you for taking the time to contribute! Please follow these guidelines to ensure a smooth and productive workflow. 🚀🚀🚀 + +To get started with the project, please refer to the [README.md](https://github.com/suitenumerique/calendars/blob/main/README.md) for detailed instructions on how to run Calendars locally. + +Contributors are required to sign off their commits with `git commit --signoff`: this confirms that they have read and accepted the [Developer's Certificate of Origin 1.1](https://developercertificate.org/). For security reasons please [sign your commits with your SSH or GPG key](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) with `git commit -S`. + +Please also check out our [dev handbook](https://suitenumerique.gitbook.io/handbook) to learn our best practices. + +## Creating an Issue + +When creating an issue, please provide the following details: + +1. **Title**: A concise and descriptive title for the issue. +2. **Description**: A detailed explanation of the issue, including relevant context or screenshots if applicable. +3. **Steps to Reproduce**: If the issue is a bug, include the steps needed to reproduce the problem. +4. **Expected vs. Actual Behavior**: Describe what you expected to happen and what actually happened. +5. **Labels**: Add appropriate labels to categorize the issue (e.g., bug, feature request, documentation). + +## Commit Message Format + +All commit messages must adhere to the following format: + +`(type) title description` + +* <**gitmoji**>: Use a gitmoji to represent the purpose of the commit. For example, ✨ for adding a new feature or 🔥 for removing something, see the list [here](https://gitmoji.dev/). +* **(type)**: Describe the type of change. Common types include `backend`, `frontend`, `CI`, `docker` etc... +* **title**: A short, descriptive title for the change (*) +* **blank line after the commit title +* **description**: Include additional details on why you made the changes (**). + +(*) ⚠️ **Make sure you add no space between the emoji and the (type) but add a space after the closing parenthesis of the type and use no caps!** + +(**) ⚠️ **Commit description message is mandatory and shouldn't be too long** + +### Example Commit Message + +``` +✨(frontend) add user authentication logic + +Implemented login and signup features, and integrated OAuth2 for social login. +``` + +## Changelog Update + +Please add a line to the changelog describing your development. The changelog entry should include a brief summary of the changes, this helps in tracking changes effectively and keeping everyone informed. We usually include the title of the pull request, followed by the pull request ID to finish the log entry. The changelog line should be less than 80 characters in total. + +### Example Changelog Message +``` +## [Unreleased] + +## Added + +- ✨(frontend) add AI to the project #321 +``` + +## Pull Requests + +It is nice to add information about the purpose of the pull request to help reviewers understand the context and intent of the changes. If you can, add some pictures or a small video to show the changes. + +### Don't forget to: +- signoff your commits +- sign your commits with your key (SSH, GPG etc.) +- check your commits (see warnings above) +- check the linting: `make lint && make frontend-lint` +- check the tests: `make test` +- add a changelog entry + +Once all the required tests have passed, you can request a review from the project maintainers. + +## Code Style + +Please maintain consistency in code style. Run any linting tools available to make sure the code is clean and follows the project's conventions. + +## Tests + +Make sure that all new features or fixes have corresponding tests. Run the test suite before pushing your changes to ensure that nothing is broken. + +## Asking for Help + +If you need any help while contributing, feel free to open a discussion or ask for guidance in the issue tracker. We are more than happy to assist! + +Thank you for your contributions! 👍 \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a9dffdd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Agence Nationale de la Cohésion des Territoires - Gouvernement Français + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..03cfe21 --- /dev/null +++ b/Makefile @@ -0,0 +1,369 @@ +# /!\ /!\ /!\ /!\ /!\ /!\ /!\ DISCLAIMER /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ +# +# This Makefile is only meant to be used for DEVELOPMENT purpose as we are +# changing the user id that will run in the container. +# +# PLEASE DO NOT USE IT FOR YOUR CI/PRODUCTION/WHATEVER... +# +# /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ +# +# Note to developers: +# +# While editing this file, please respect the following statements: +# +# 1. Every variable should be defined in the ad hoc VARIABLES section with a +# relevant subsection +# 2. Every new rule should be defined in the ad hoc RULES section with a +# relevant subsection depending on the targeted service +# 3. Rules should be sorted alphabetically within their section +# 4. When a rule has multiple dependencies, you should: +# - duplicate the rule name to add the help string (if required) +# - write one dependency per line to increase readability and diffs +# 5. .PHONY rule statement should be written after the corresponding rule +# ============================================================================== +# VARIABLES + +BOLD := \033[1m +RESET := \033[0m +GREEN := \033[1;32m + + +# -- Database + +DB_HOST = postgresql +DB_PORT = 5432 + +# -- Docker +# Get the current user ID to use for docker run and docker exec commands +DOCKER_UID = $(shell id -u) +DOCKER_GID = $(shell id -g) +DOCKER_USER = $(DOCKER_UID):$(DOCKER_GID) +COMPOSE = DOCKER_USER=$(DOCKER_USER) docker compose +COMPOSE_EXEC = $(COMPOSE) exec +COMPOSE_EXEC_APP = $(COMPOSE_EXEC) backend-dev +COMPOSE_RUN = $(COMPOSE) run --rm +COMPOSE_RUN_APP = $(COMPOSE_RUN) backend-dev +COMPOSE_RUN_APP_NO_DEPS = $(COMPOSE_RUN) --no-deps backend-dev + +COMPOSE_RUN_CROWDIN = $(COMPOSE_RUN) crowdin crowdin + +# -- Backend +MANAGE = $(COMPOSE_RUN_APP) python manage.py +MANAGE_EXEC = $(COMPOSE_EXEC_APP) python manage.py +PSQL_E2E = ./bin/postgres_e2e + +# -- Frontend +PATH_FRONT = ./src/frontend +PATH_FRONT_CALENDARS = $(PATH_FRONT)/apps/calendars + +# ============================================================================== +# RULES + +default: help + +data/media: + @mkdir -p data/media + +data/static: + @mkdir -p data/static + +# -- Project + +create-env-files: ## Create empty .local env files for local development +create-env-files: \ + env.d/development/crowdin.local \ + env.d/development/postgresql.local \ + env.d/development/keycloak.local \ + env.d/development/backend.local \ + env.d/development/frontend.local \ + env.d/development/davical.local +.PHONY: create-env-files + +env.d/development/%.local: + @echo "# Local development overrides for $(notdir $*)" > $@ + @echo "# Add your local-specific environment variables below:" >> $@ + @echo "# Example: DJANGO_DEBUG=True" >> $@ + @echo "" >> $@ +.PHONY: env.d/development/%.local + +create-docker-network: ## create the docker network if it doesn't exist + @docker network create lasuite-network || true +.PHONY: create-docker-network + +bootstrap: ## Prepare Docker images for the project +bootstrap: \ + data/media \ + data/static \ + create-env-files \ + build \ + create-docker-network \ + migrate \ + migrate-davical \ + back-i18n-compile \ + run +.PHONY: bootstrap + +# -- Docker/compose +build: cache ?= # --no-cache +build: ## build the project containers + @$(MAKE) build-backend cache=$(cache) + @$(MAKE) build-frontend cache=$(cache) +.PHONY: build + +build-backend: cache ?= +build-backend: ## build the backend-dev container + @$(COMPOSE) build backend-dev $(cache) +.PHONY: build-backend + +build-frontend: cache ?= +build-frontend: ## build the frontend container + @$(COMPOSE) build frontend-dev $(cache) +.PHONY: build-frontend-development + +down: ## stop and remove containers, networks, images, and volumes + @$(COMPOSE) down + rm -rf data/postgresql.* +.PHONY: down + +logs: ## display backend-dev logs (follow mode) + @$(COMPOSE) logs -f backend-dev +.PHONY: logs + +run-backend: ## start the backend container + @$(COMPOSE) up --force-recreate -d celery-dev + @$(COMPOSE) up --force-recreate -d nginx +.PHONY: run-backend + +bootstrap-e2e: ## bootstrap the backend container for e2e tests, without frontend +bootstrap-e2e: \ + data/media \ + data/static \ + create-env-local-files \ + build-backend \ + create-docker-network \ + back-i18n-compile \ + run-backend-e2e +.PHONY: bootstrap-e2e + +clear-db-e2e: ## quickly clears the database for e2e tests, used in the e2e tests + $(PSQL_E2E) -c "$$(cat bin/clear_db_e2e.sql)" +.PHONY: clear-db-e2e + +run-backend-e2e: ## start the backend container for e2e tests, always remove the postgresql.e2e volume first + @$(MAKE) stop + rm -rf data/postgresql.e2e + @ENV_OVERRIDE=e2e $(MAKE) run-backend + @ENV_OVERRIDE=e2e $(MAKE) migrate +.PHONY: run-backend-e2e + +run-tests-e2e: ## run the e2e tests, example: make run-tests-e2e -- --project chromium --headed + @$(MAKE) run-backend-e2e + @args="$(filter-out $@,$(MAKECMDGOALS))" && \ + cd src/frontend/apps/e2e && yarn test $${args:-${1}} +.PHONY: run-tests-e2e + +backend-exec-command: ## execute a command in the backend container + @args="$(filter-out $@,$(MAKECMDGOALS))" && \ + $(MANAGE_EXEC) $${args} +.PHONY: backend-exec-command + +run: ## start the development server and frontend development +run: + @$(MAKE) run-backend + @$(COMPOSE) up --force-recreate -d frontend-dev + +migrate-davical: ## Initialize DAViCal database schema + @echo "$(BOLD)Initializing DAViCal database schema...$(RESET)" + @$(COMPOSE) run --rm davical run-migrations + @echo "$(GREEN)DAViCal initialized$(RESET)" +.PHONY: migrate-davical + +status: ## an alias for "docker compose ps" + @$(COMPOSE) ps +.PHONY: status + +stop: ## stop the development server using Docker + @$(COMPOSE) stop +.PHONY: stop + +# -- Backend + +demo: ## flush db then create a demo for load testing purpose + @$(MAKE) resetdb + @$(MANAGE) create_demo +.PHONY: demo + +index: ## index all files to remote search + @$(MANAGE) index +.PHONY: index + +# Nota bene: Black should come after isort just in case they don't agree... +lint: ## lint back-end python sources +lint: \ + lint-ruff-format \ + lint-ruff-check \ + lint-pylint +.PHONY: lint + +lint-ruff-format: ## format back-end python sources with ruff + @echo 'lint:ruff-format started…' + @$(COMPOSE_RUN_APP_NO_DEPS) ruff format . +.PHONY: lint-ruff-format + +lint-ruff-check: ## lint back-end python sources with ruff + @echo 'lint:ruff-check started…' + @$(COMPOSE_RUN_APP_NO_DEPS) ruff check . --fix +.PHONY: lint-ruff-check + +lint-pylint: ## lint back-end python sources with pylint only on changed files from main + @echo 'lint:pylint started…' + bin/pylint --diff-only=origin/main +.PHONY: lint-pylint + +test: ## run project tests + @$(MAKE) test-back-parallel +.PHONY: test + +test-back: ## run back-end tests + @args="$(filter-out $@,$(MAKECMDGOALS))" && \ + bin/pytest $${args:-${1}} +.PHONY: test-back + +test-back-parallel: ## run all back-end tests in parallel + @args="$(filter-out $@,$(MAKECMDGOALS))" && \ + bin/pytest -n auto $${args:-${1}} +.PHONY: test-back-parallel + +makemigrations: ## run django makemigrations for the calendar project. + @echo "$(BOLD)Running makemigrations$(RESET)" + @$(COMPOSE) up -d postgresql + @$(MANAGE) makemigrations +.PHONY: makemigrations + +migrate: ## run django migrations for the calendar project. + @echo "$(BOLD)Running migrations$(RESET)" + @$(COMPOSE) up -d postgresql + @$(MANAGE) migrate +.PHONY: migrate + +superuser: ## Create an admin superuser with password "admin" + @echo "$(BOLD)Creating a Django superuser$(RESET)" + @$(MANAGE) createsuperuser --email admin@example.com --password admin +.PHONY: superuser + + +back-i18n-compile: ## compile the gettext files + @$(MANAGE) compilemessages --ignore=".venv/**/*" +.PHONY: back-i18n-compile + +back-lock: ## regenerate the uv.lock file (uses temporary container) + @echo "$(BOLD)Regenerating uv.lock$(RESET)" + @docker run --rm -v $(PWD)/src/backend:/app -w /app ghcr.io/astral-sh/uv:python3.13-alpine uv lock +.PHONY: back-lock + +back-i18n-generate: ## create the .pot files used for i18n + @$(MANAGE) makemessages -a --keep-pot --all +.PHONY: back-i18n-generate + +back-shell: ## open a shell in the backend container + @$(COMPOSE) run --rm --build backend-dev /bin/sh +.PHONY: back-shell + +shell: ## connect to django shell + @$(MANAGE) shell #_plus +.PHONY: shell + +# -- Database + +dbshell: ## connect to database shell + docker compose exec backend-dev python manage.py dbshell +.PHONY: dbshell + +resetdb: FLUSH_ARGS ?= +resetdb: ## flush database and create a superuser "admin" + @echo "$(BOLD)Flush database$(RESET)" + @$(MANAGE) flush $(FLUSH_ARGS) + @${MAKE} superuser +.PHONY: resetdb + +# -- Internationalization + +crowdin-download: ## Download translated message from crowdin + @$(COMPOSE_RUN_CROWDIN) download -c crowdin/config.yml +.PHONY: crowdin-download + +crowdin-download-sources: ## Download sources from Crowdin + @$(COMPOSE_RUN_CROWDIN) download sources -c crowdin/config.yml +.PHONY: crowdin-download-sources + +crowdin-upload: ## Upload source translations to crowdin + @$(COMPOSE_RUN_CROWDIN) upload sources -c crowdin/config.yml +.PHONY: crowdin-upload + +i18n-compile: ## compile all translations +i18n-compile: \ + back-i18n-compile \ + frontend-i18n-compile +.PHONY: i18n-compile + +i18n-generate: ## create the .pot files and extract frontend messages +i18n-generate: \ + back-i18n-generate \ + frontend-i18n-generate +.PHONY: i18n-generate + +i18n-download-and-compile: ## download all translated messages and compile them to be used by all applications +i18n-download-and-compile: \ + crowdin-download \ + i18n-compile +.PHONY: i18n-download-and-compile + +i18n-generate-and-upload: ## generate source translations for all applications and upload them to Crowdin +i18n-generate-and-upload: \ + i18n-generate \ + crowdin-upload +.PHONY: i18n-generate-and-upload + + +# -- Misc +clean: ## restore repository state as it was freshly cloned + git clean -idx +.PHONY: clean + +clean-media: ## remove all media files + rm -rf data/media/* +.PHONY: clean-media + +help: + @echo "$(BOLD)calendar Makefile" + @echo "Please use 'make $(BOLD)target$(RESET)' where $(BOLD)target$(RESET) is one of:" + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(GREEN)%-30s$(RESET) %s\n", $$1, $$2}' +.PHONY: help + +# Front +frontend-development-install: ## install the frontend locally + cd $(PATH_FRONT_CALENDARS) && yarn +.PHONY: frontend-development-install + +frontend-lint: ## run the frontend linter + cd $(PATH_FRONT) && yarn lint +.PHONY: frontend-lint + +run-frontend-development: ## Run the frontend in development mode + @$(COMPOSE) stop frontend-dev + cd $(PATH_FRONT_CALENDARS) && yarn dev +.PHONY: run-frontend-development + +frontend-i18n-extract: ## Extract the frontend translation inside a json to be used for crowdin + cd $(PATH_FRONT) && yarn i18n:extract +.PHONY: frontend-i18n-extract + +frontend-i18n-generate: ## Generate the frontend json files used for crowdin +frontend-i18n-generate: \ + crowdin-download-sources \ + frontend-i18n-extract +.PHONY: frontend-i18n-generate + +frontend-i18n-compile: ## Format the crowin json files used deploy to the apps + cd $(PATH_FRONT) && yarn i18n:deploy +.PHONY: frontend-i18n-compile diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..700057e --- /dev/null +++ b/Procfile @@ -0,0 +1,3 @@ +web: bin/scalingo_run_web +worker: celery -A calendars.celery_app worker --task-events --beat -l INFO -c $DJANGO_CELERY_CONCURRENCY -Q celery,default +postdeploy: python manage.py migrate diff --git a/README.md b/README.md new file mode 100644 index 0000000..d51a531 --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ +

+ + Calendars banner + +

+

+ GitHub commit activity + GitHub closed issues + + GitHub closed issues + +

+ +

+ + Chat on Matrix + - + Documentation + - + Getting started + - + Reach out + +

+ +# La Suite Calendars +A modern calendar application for managing events and schedules. + + + + +## Why use Calendars ❓ +Calendars empowers teams to manage events and schedules while maintaining full control over their data through a user-friendly, open-source platform. + +### Manage Events +- 📅 Create and manage events and schedules +- 🌐 Access your calendar from anywhere with our web-based interface + +### Organize +- 📂 Organized calendar structure with intuitive navigation + +### Collaborate +- 🤝 Share calendars with your team members +- 👥 Granular access control to ensure your information is secure and only shared with the right people +- 🏢 Create workspaces to organize team collaboration + +### Self-host +* 🚀 Easy to install, scalable and secure calendar solution + +## Getting started 🔧 + +### Prerequisite + +Make sure you have a recent version of Docker and [Docker +Compose](https://docs.docker.com/compose/install) installed on your laptop: + +```bash +$ docker -v + Docker version 27.5.1, build 9f9e405 + +$ docker compose version + Docker Compose version v2.32.4 +``` + +> ⚠️ You may need to run the following commands with `sudo` but this can be +> avoided by assigning your user to the `docker` group. + +### Bootstrap project + +The easiest way to start working on the project is to use GNU Make: + +```bash +$ make bootstrap +``` + +This command builds the `backend-dev` and `frontend-dev` containers, installs dependencies, performs +database migrations and compile translations. It's a good idea to use this +command each time you are pulling code from the project repository to avoid +dependency-related or migration-related issues. + +Your Docker services should now be up and running! 🎉 + +You can access the project by going to . + +You will be prompted to log in. The default credentials are: + +``` +username: calendars +password: calendars +``` + +Note that if you need to run them afterward, you can use the eponym Make rule: + +```bash +$ make run +``` + +You can check all available Make rules using: + +```bash +$ make help +``` + +⚠️ For the frontend developer, it is often better to run the frontend in development mode locally. + +To do so, install the frontend dependencies with the following command: + +```shellscript +$ make frontend-development-install +``` + +And run the frontend locally in development mode with the following command: + +```shellscript +$ make run-frontend-development +``` + +To start all the services, except the frontend container, you can use the following command: + +```shellscript +$ make run-backend +``` + +### Django admin + +You can access the Django admin site at +[http://localhost:8921/admin](http://localhost:8921/admin). + +You first need to create a superuser account: + +```bash +$ make superuser +``` + +You can then login with sub `admin@example.com` and password `admin`. + + +## Feedback 🙋‍♂️🙋‍♀️ + +We'd love to hear your thoughts and hear about your experiments, so come and say hi on [Matrix](https://matrix.to/#/#messages-official:matrix.org). + +## Contributing 🙌 + +This project is intended to be community-driven, so please, do not hesitate to get in touch if you have any question related to our implementation or design +decisions. + +## License 📝 + +This work is released under the MIT License (see [LICENSE](./LICENSE)). + +While Calendars is a public driven initiative our licence choice is an invitation for private sector actors to use, sell and contribute to the project. + +## Credits ❤️ + +Calendars is built on top of [Django Rest Framework](https://www.django-rest-framework.org/), [Next.js](https://nextjs.org/). We thank the contributors of all these projects for their awesome work! diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..7a4d5ba --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Reporting a Vulnerability + +Security is very important to us. + +If you have any issue regarding security, please disclose the information responsibly emailing us at security@suite.anct.gouv.fr + +We appreciate your effort to make Calendars more secure. + +## Vulnerability disclosure policy + +Working with security issues in an open source project can be challenging, as we are required to disclose potential problems that could be exploited by attackers. With this in mind, our security fix policy is as follows: + +1. The Maintainers team will handle the fix as usual (Pull Request, +release). +2. In the release notes, we will include the identification numbers from the +GitHub Advisory Database (GHSA) and, if applicable, the Common Vulnerabilities +and Exposures (CVE) identifier for the vulnerability. +3. Once this grace period has passed, we will publish the vulnerability. + +By adhering to this security policy, we aim to address security concerns +effectively and responsibly in our open source software project. \ No newline at end of file diff --git a/bin/_config.sh b/bin/_config.sh new file mode 100644 index 0000000..071f9d3 --- /dev/null +++ b/bin/_config.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +set -eo pipefail + +REPO_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd)" +UNSET_USER=0 + +if [ -z ${COMPOSE_FILE+x} ]; then + COMPOSE_FILE="${REPO_DIR}/compose.yaml" +fi + +# _set_user: set (or unset) default user id used to run docker commands +# +# usage: _set_user +# +# You can override default user ID (the current host user ID), by defining the +# USER_ID environment variable. +# +# To avoid running docker commands with a custom user, please set the +# $UNSET_USER environment variable to 1. +function _set_user() { + + if [ $UNSET_USER -eq 1 ]; then + USER_ID="" + return + fi + + # USER_ID = USER_ID or `id -u` if USER_ID is not set + USER_ID=${USER_ID:-$(id -u)} + + echo "🙋(user) ID: ${USER_ID}" +} + +# docker_compose: wrap docker compose command +# +# usage: docker_compose [options] [ARGS...] +# +# options: docker compose command options +# ARGS : docker compose command arguments +function _docker_compose() { + + echo "🐳(compose) project, file: '${COMPOSE_FILE}'" + docker compose \ + -f "${COMPOSE_FILE}" \ + --project-directory "${REPO_DIR}" \ + "$@" +} + +# _dc_run: wrap docker compose run command +# +# usage: _dc_run [options] [ARGS...] +# +# options: docker compose run command options +# ARGS : docker compose run command arguments +function _dc_run() { + _set_user + + user_args="--user=$USER_ID" + if [ -z $USER_ID ]; then + user_args="" + fi + + _docker_compose run --rm $user_args "$@" +} + +# _dc_exec: wrap docker compose exec command +# +# usage: _dc_exec [options] [ARGS...] +# +# options: docker compose exec command options +# ARGS : docker compose exec command arguments +function _dc_exec() { + _set_user + + echo "🐳(compose) exec command: '\$@'" + + user_args="--user=$USER_ID" + if [ -z $USER_ID ]; then + user_args="" + fi + + _docker_compose exec $user_args "$@" +} + +# _django_manage: wrap django's manage.py command with docker compose +# +# usage : _django_manage [ARGS...] +# +# ARGS : django's manage.py command arguments +function _django_manage() { + _dc_run "backend-dev" python manage.py "$@" +} + diff --git a/bin/clear_db_e2e.sql b/bin/clear_db_e2e.sql new file mode 100644 index 0000000..6a2c0a1 --- /dev/null +++ b/bin/clear_db_e2e.sql @@ -0,0 +1,9 @@ +DO $$ +DECLARE r RECORD; +BEGIN + FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename != 'django_migrations') + LOOP + RAISE NOTICE 'Truncating table %', r.tablename; + EXECUTE 'TRUNCATE TABLE ' || quote_ident(r.tablename) || ' CASCADE'; + END LOOP; +END $$; diff --git a/bin/compose b/bin/compose new file mode 100755 index 0000000..1adb3d8 --- /dev/null +++ b/bin/compose @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# shellcheck source=bin/_config.sh +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +_docker_compose "$@" diff --git a/bin/fernetkey b/bin/fernetkey new file mode 100755 index 0000000..92b6b4c --- /dev/null +++ b/bin/fernetkey @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# shellcheck source=bin/_config.sh +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +_dc_run backend-dev python -c 'from cryptography.fernet import Fernet;import sys; sys.stdout.write("\n" + Fernet.generate_key().decode() + "\n");' diff --git a/bin/manage b/bin/manage new file mode 100755 index 0000000..b6c82d9 --- /dev/null +++ b/bin/manage @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# shellcheck source=bin/_config.sh +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +_django_manage "$@" diff --git a/bin/postgres_e2e b/bin/postgres_e2e new file mode 100755 index 0000000..8d2f6e4 --- /dev/null +++ b/bin/postgres_e2e @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# shellcheck source=bin/_config.sh +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +# Get database credentials from environment file +ENV_FILE="${REPO_DIR}/env.d/development/postgresql.e2e" +POSTGRES_USER=$(grep POSTGRES_USER "$ENV_FILE" | cut -d'=' -f2) +POSTGRES_DB=$(grep POSTGRES_DB "$ENV_FILE" | cut -d'=' -f2) + +# Execute PostgreSQL command (run as postgres user, not host user) +_docker_compose exec -T postgresql psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 "$@" diff --git a/bin/pylint b/bin/pylint new file mode 100755 index 0000000..f58bdb8 --- /dev/null +++ b/bin/pylint @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# shellcheck source=bin/_config.sh +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +declare diff_from +declare -a paths +declare -a args + +# Parse options +for arg in "$@" +do + case $arg in + --diff-only=*) + diff_from="${arg#*=}" + shift + ;; + -*) + args+=("$arg") + shift + ;; + *) + paths+=("$arg") + shift + ;; + esac +done + +if [[ -n "${diff_from}" ]]; then + # Run pylint only on modified files located in src/backend + # (excluding deleted files and migration files) + # shellcheck disable=SC2207 + paths=($(git diff "${diff_from}" --name-only --diff-filter=d -- src/backend ':!**/migrations/*.py' | grep -E '^src/backend/.*\.py$')) +fi + +# Fix docker vs local path when project sources are mounted as a volume +read -ra paths <<< "$(echo "${paths[@]}" | sed "s|src/backend/||g")" +_dc_run --no-deps backend-dev pylint "${paths[@]}" "${args[@]}" diff --git a/bin/pytest b/bin/pytest new file mode 100755 index 0000000..bd3b0d1 --- /dev/null +++ b/bin/pytest @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +_dc_run \ + -e DJANGO_CONFIGURATION=Test \ + backend-dev \ + pytest "$@" diff --git a/bin/scalingo_postcompile b/bin/scalingo_postcompile new file mode 100644 index 0000000..425f8c0 --- /dev/null +++ b/bin/scalingo_postcompile @@ -0,0 +1,11 @@ +#!/bin/bash + +set -o errexit # always exit on error +set -o pipefail # don't ignore exit codes when piping output + +echo "-----> Running post-compile script" + +# Remove all the files we don't need +rm -rf src docker env.d .cursor .github compose.yaml README.md .cache + +chmod +x bin/scalingo_run_web diff --git a/bin/scalingo_postfrontend b/bin/scalingo_postfrontend new file mode 100644 index 0000000..6036678 --- /dev/null +++ b/bin/scalingo_postfrontend @@ -0,0 +1,15 @@ +#!/bin/bash + +set -o errexit # always exit on error +set -o pipefail # don't ignore exit codes when piping output + +echo "-----> Running post-frontend script" + +# Move the frontend build to the nginx root and clean up +mkdir -p build/ +mv src/frontend/apps/calendars/out build/frontend-out + +mv src/backend/* ./ +mv src/nginx/* ./ + +echo "3.13" > .python-version diff --git a/bin/scalingo_run_web b/bin/scalingo_run_web new file mode 100644 index 0000000..cac67f4 --- /dev/null +++ b/bin/scalingo_run_web @@ -0,0 +1,15 @@ +#!/bin/bash + +# Start the Django backend +gunicorn -b :8000 calendars.wsgi:application --log-file - & + +# Start the Nginx server +bin/run & + +# if the current shell is killed, also terminate all its children +trap "pkill SIGTERM -P $$" SIGTERM + +# wait for a single child to finish, +wait -n +# then kill all the other tasks +pkill -P $$ diff --git a/bin/update_app_cacert.sh b/bin/update_app_cacert.sh new file mode 100755 index 0000000..4011503 --- /dev/null +++ b/bin/update_app_cacert.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -o errexit + +# The script is pretty simple. It downloads the latest cacert.pem file from the certifi package and appends the root certificate from mkcert to it. Then it copies the updated cacert.pem file to the container. +# The script is executed with the following command: +# $ bin/update_app_cacert.sh docs-production-backend-1 + +CONTAINER_NAME=${1:-"calendars-production-backend-1"} + +echo "updating cacert.pem for certifi package in ${CONTAINER_NAME}" + + +curl --create-dirs https://raw.githubusercontent.com/certifi/python-certifi/refs/heads/master/certifi/cacert.pem -o /tmp/certifi/cacert.pem +cat "$(mkcert -CAROOT)/rootCA.pem" >> /tmp/certifi/cacert.pem +docker cp /tmp/certifi/cacert.pem ${CONTAINER_NAME}:/usr/local/lib/python3.12/site-packages/certifi/cacert.pem + +echo "end patching cacert.pem in ${CONTAINER_NAME}" diff --git a/bin/update_openapi_schema b/bin/update_openapi_schema new file mode 100755 index 0000000..ac28aa5 --- /dev/null +++ b/bin/update_openapi_schema @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +source "$(dirname "${BASH_SOURCE[0]}")/_config.sh" + +_dc_run \ + -e DJANGO_CONFIGURATION=Test \ + backend-dev \ + python manage.py spectacular \ + --api-version 'v1.0' \ + --urlconf 'calendars.api_urls' \ + --format openapi-json \ + --file /app/core/tests/swagger/swagger.json diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..d7f8daa --- /dev/null +++ b/compose.yaml @@ -0,0 +1,183 @@ +name: calendars + +services: + # Shared PostgreSQL for all services (calendar, davical, keycloak) + postgresql: + image: postgres:15 + ports: + - "8912:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + interval: 1s + timeout: 2s + retries: 300 + env_file: + - env.d/development/postgresql.defaults + - env.d/development/postgresql.local + + redis: + image: redis:5 + ports: + - "6379:6379" + + mailcatcher: + image: sj26/mailcatcher:latest + ports: + - "1081:1080" + + backend-dev: + build: + context: src/backend + target: backend-development + args: + DOCKER_USER: ${DOCKER_USER:-1000} + user: ${DOCKER_USER:-1000} + image: calendars:backend-development + environment: + - PYLINTHOME=/app/.pylint.d + - DJANGO_CONFIGURATION=Development + - DAVICAL_URL=http://davical:80 + env_file: + - env.d/development/backend.defaults + - env.d/development/backend.local + ports: + - "8921:8000" + volumes: + - ./src/backend:/app + - ./data/static:/data/static + - /app/.venv + networks: + - lasuite + - default + depends_on: + postgresql: + condition: service_healthy + restart: true + mailcatcher: + condition: service_started + redis: + condition: service_started + celery-dev: + condition: service_started + davical: + condition: service_started + + celery-dev: + user: ${DOCKER_USER:-1000} + image: calendars:backend-development + networks: + - default + - lasuite + command: ["celery", "-A", "calendars.celery_app", "worker", "-l", "DEBUG"] + environment: + - DJANGO_CONFIGURATION=Development + env_file: + - env.d/development/backend.defaults + - env.d/development/backend.local + volumes: + - ./src/backend:/app + - ./data/static:/data/static + - /app/.venv + + nginx: + image: nginx:1.25 + ports: + - "8923:8083" + networks: + default: {} + lasuite: + aliases: + - nginx + volumes: + - ./docker/files/development/etc/nginx/conf.d:/etc/nginx/conf.d:ro + depends_on: + - keycloak + - backend-dev + + frontend-dev: + user: "${DOCKER_USER:-1000}" + build: + context: src/frontend + target: calendars-dev + args: + API_ORIGIN: "http://localhost:8921" + image: calendars:frontend-development + env_file: + - env.d/development/frontend.defaults + - env.d/development/frontend.local + volumes: + - ./src/frontend/:/home/frontend/ + - /home/frontend/node_modules + - /home/frontend/apps/calendars/node_modules + - /home/frontend/packages/open-calendar/dist + - /home/frontend/packages/open-calendar/node_modules + ports: + - "8920:3000" + + crowdin: + image: crowdin/cli:3.16.0 + volumes: + - ".:/app" + env_file: + - env.d/development/crowdin.defaults + - env.d/development/crowdin.local + user: "${DOCKER_USER:-1000}" + working_dir: /app + + node: + image: node:22 + user: "${DOCKER_USER:-1000}" + environment: + HOME: /tmp + volumes: + - ".:/app" + + # DAViCal CalDAV Server + davical: + image: fintechstudios/davical:latest + platform: linux/amd64 + ports: + - "8922:80" + env_file: + - env.d/development/davical.defaults + - env.d/development/davical.local + volumes: + # Mount our custom config.php if we need to override defaults + - ./docker/davical/config.php:/etc/davical/config.php:ro + - ./docker/davical/run-migrations:/usr/local/bin/run-migrations:ro + networks: + - default + - lasuite + depends_on: + postgresql: + condition: service_healthy + + # Keycloak - now using shared PostgreSQL + keycloak: + image: quay.io/keycloak/keycloak:26.3.2 + volumes: + - ./docker/auth/realm.json:/opt/keycloak/data/import/realm.json + command: + - start-dev + - --features=preview + - --import-realm + - --hostname=http://localhost:8925 + - --hostname-strict=false + env_file: + - env.d/development/keycloak.defaults + - env.d/development/keycloak.local + ports: + - "8925:8080" + depends_on: + postgresql: + condition: service_healthy + networks: + - lasuite + - default + +networks: + default: {} + lasuite: + name: lasuite-network + driver: bridge + external: true diff --git a/cron.json b/cron.json new file mode 100644 index 0000000..61675d3 --- /dev/null +++ b/cron.json @@ -0,0 +1,7 @@ +{ + "jobs": [ + { + "command": "0 0 * * * bin/scalingo_pgdump.sh" + } + ] +} diff --git a/docker/auth/realm.json b/docker/auth/realm.json new file mode 100644 index 0000000..13cd002 --- /dev/null +++ b/docker/auth/realm.json @@ -0,0 +1,2358 @@ +[ + { + "realm": "master", + "sslRequired": "none", + "enabled": true + }, + { + "id": "ccf4fd40-4286-474d-854a-4714282a8bec", + "realm": "calendars", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "none", + "registrationAllowed": true, + "registrationEmailAsUsername": false, + "rememberMe": true, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": true, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "users": [ + { + "username": "calendars", + "email": "calendars@calendars.world", + "firstName": "John", + "lastName": "Doe", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "calendars" + } + ], + "realmRoles": ["user"] + }, + { + "username": "user-e2e-chromium", + "email": "user@chromium.test", + "firstName": "E2E", + "lastName": "Chromium", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "password-e2e-chromium" + } + ], + "realmRoles": ["user"] + }, + { + "username": "user-e2e-webkit", + "email": "user@webkit.test", + "firstName": "E2E", + "lastName": "Webkit", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "password-e2e-webkit" + } + ], + "realmRoles": ["user"] + }, + { + "username": "user-e2e-firefox", + "email": "user@firefox.test", + "firstName": "E2E", + "lastName": "Firefox", + "enabled": true, + "credentials": [ + { + "type": "password", + "value": "password-e2e-firefox" + } + ], + "realmRoles": ["user"] + } + ], + "roles": { + "realm": [ + { + "id": "1f116065-05b6-4269-80a6-c7d904b584b7", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec", + "attributes": {} + }, + { + "id": "1bfe401a-08fc-4d94-80e0-86c4f5195f99", + "name": "default-roles-calendars", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": ["offline_access", "uma_authorization"], + "client": { + "account": ["view-profile", "manage-account"] + } + }, + "clientRole": false, + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec", + "attributes": {} + }, + { + "id": "8733db03-278a-45ad-a25e-c167fbd95b5a", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "9dcc0883-e2e5-4671-9159-402bdbe73c57", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "ae911be0-ea2e-466d-93e0-f8e73fa8f444", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e777d332-7205-4b76-8b21-9191a2e85a0d", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b1a95608-d518-4ede-936e-525ab704d363", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "ac58976a-ae55-4d92-a864-b33e21b07c54", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "a149b28f-d252-4ceb-8ba9-8161603c4184", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "00a5b886-7ca4-4fba-90c6-a9071e697d86", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b22d5cc1-879e-4405-8345-cc204fd0fec0", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "impersonation", + "view-authorization", + "manage-authorization", + "create-client", + "view-events", + "manage-identity-providers", + "manage-clients", + "view-identity-providers", + "query-users", + "manage-users", + "view-clients", + "view-users", + "manage-events", + "view-realm", + "query-realms", + "query-groups", + "manage-realm", + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b3e9faf6-17bf-4f62-abd5-07837806a7e6", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "a8d85f42-023b-48dd-8f49-c9da2b5317ee", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "eb325a4d-db7a-4f6a-a88b-0ff8aa38b0a5", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "267bb612-62f4-4354-abb2-ac6a34bd854b", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "b575be2b-e250-4000-b75e-3038cda8c0dd", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e19cd0bf-8da0-457d-b630-454c611bc1ba", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": ["query-users", "query-groups"] + } + }, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "c12145cc-cbdc-4ef3-9774-19b1852811ba", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e7e15b84-4971-4c13-be93-315bb36d30e1", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "e03d2989-a620-4918-85ed-3eabd0373bb4", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "daf8d347-4b30-41d6-a431-7b3723dd8e6f", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + }, + { + "id": "432cd3eb-4741-46ba-938a-94ff9dece315", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "2e713186-38da-44d7-a5a5-19d91ef2dfca", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "41dd8f26-46c2-471a-859e-01886f972ff9", + "attributes": {} + } + ], + "calendars": [], + "account": [ + { + "id": "63b1a4e1-a594-4571-99c3-7c5c3efd61ce", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": ["view-consent"] + } + }, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "36ef5fd6-1167-4ba0-9171-c8cb6cfe904b", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "f984654a-fca5-45d9-bb47-73009eb9bcf0", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "d54168c5-58a5-4f13-9fa8-6dbbee0e4b73", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": ["manage-account-links"] + } + }, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "092b6808-1ee2-44be-9b5d-085ccd6862b4", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "ddd57af0-2a5e-4f9d-98e5-ec96c8d852ce", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "84c7324a-4724-41fe-8bd4-848ce5cebd5b", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + }, + { + "id": "20d06f75-ea65-4b99-b9ef-2384ffd1de53", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "06721011-1061-4ca7-944f-be2a20719e20", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "1bfe401a-08fc-4d94-80e0-86c4f5195f99", + "name": "default-roles-calendars", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "ccf4fd40-4286-474d-854a-4714282a8bec" + }, + "requiredCredentials": ["password"], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": ["totpAppGoogleName", "totpAppFreeOTPName"], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": ["ES256"], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": ["offline_access"] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": ["manage-account", "view-groups"] + } + ] + }, + "clients": [ + { + "id": "06721011-1061-4ca7-944f-be2a20719e20", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/calendars/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": ["/realms/calendars/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "987e14a5-caed-40a6-8bac-8c429b74ca48", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/calendars/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": ["/realms/calendars/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "4f958126-eaa1-46d5-967a-3a3c2e2d11f7", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "92da37ad-e8a1-41f1-93c6-541dffa7d601", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "41dd8f26-46c2-471a-859e-01886f972ff9", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "869481d0-5774-4e64-bc30-fedc7c58958f", + "clientId": "calendars", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "ThisIsAnExampleKeyForDevPurposeOnly", + "redirectUris": [ + "http://localhost:8920/*", + "http://localhost:8921/*", + "http://localhost:8922/*", + "http://localhost:8923/*" + ], + "webOrigins": [ + "http://localhost:8920", + "http://localhost:8921", + "http://localhost:8922", + "http://localhost:8923" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "access.token.lifespan": "-1", + "client.secret.creation.time": "1707820779", + "user.info.response.signature.alg": "RS256", + "post.logout.redirect.uris": "http://localhost:8920/*##http://localhost:8921/*", + "oauth2.device.authorization.grant.enabled": "false", + "use.jwks.url": "false", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "tls-client-certificate-bound-access-tokens": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "acr.loa.map": "{}", + "require.pushed.authorization.requests": "false", + "display.on.consent.screen": "false", + "client.session.idle.timeout": "-1", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "869481d0-5774-4e64-bc30-fedc7c58958g", + "clientId": "deploycenter", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "ThisIsAnExampleKeyForDevPurposeOnly", + "redirectUris": [ + "http://localhost:8920/*", + "http://localhost:8921/*", + "http://localhost:8922/*", + "http://localhost:8923/*" + ], + "webOrigins": [ + "http://localhost:8920", + "http://localhost:8921", + "http://localhost:8922", + "http://localhost:8923" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "access.token.lifespan": "-1", + "client.secret.creation.time": "1707820779", + "user.info.response.signature.alg": "RS256", + "post.logout.redirect.uris": "http://localhost:8920/*##http://localhost:8921/*", + "oauth2.device.authorization.grant.enabled": "false", + "use.jwks.url": "false", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "tls-client-certificate-bound-access-tokens": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "acr.loa.map": "{}", + "require.pushed.authorization.requests": "false", + "display.on.consent.screen": "false", + "client.session.idle.timeout": "-1", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "0d004a05-7049-452c-83a8-2bae2b5d8015", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "2a4e007a-2fc4-4f43-aace-b93aec9221b4", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/calendars/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": ["/admin/calendars/console/*"], + "webOrigins": ["+"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "4913be96-5827-46a4-9909-562c2dd5bef6", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "74aeb8e2-a1b6-4897-9eaf-d922becea170", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "994b8f5e-dfc1-4154-a936-347336e6422a", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "d853f97e-80f8-470e-8447-815b289d9ae3", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "id": "26a9f3ef-cff0-4dee-9fe9-778cd1d2a771", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "af52ccc3-4ecb-49b4-9a67-5d4172f16070", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "efb82630-8835-4de0-944e-ac5ea51eca48", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "2256189a-7970-4244-b496-64cbba3ce582", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "6d7f8b9e-997e-40f8-bae5-83d2647fbeff", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "b83cebb6-f086-48e2-8e5a-9802736342f2", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "b99113c6-ccfb-43d4-acd1-09dd34cdf5bc", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "696211d7-c434-495f-b3a0-a1b88bebfd6e", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "16845bd9-5626-4484-b4c5-00af52d8ad8b", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "5828a7d9-cdc7-456b-a747-16bf83c2f57d", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "ce289e05-eca4-4323-b457-822d39cc6d49", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "abe63488-9a39-4e29-a0a8-824db0887b60", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "15690cfb-e14c-46e8-8494-22a0365a4b0c", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "03cf0e4c-c2a5-4203-88c4-5391d361ba15", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "23b1a1da-2ecc-4db7-8d33-4e9233a81e89", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "26a72777-56eb-4b46-acca-eca8168e29fc", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "4ae1896b-ea82-4604-8f0e-72133fdee05c", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "79712bcf-b7f7-4ca3-b97c-418f48fded9b", + "name": "first name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "first_name", + "jsonType.label": "String" + } + }, + { + "id": "6397c5e9-95ea-4c31-bd44-a8acf1d18472", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "7f741e96-41fe-4021-bbfd-506e7eb94e69", + "name": "last name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "last_name", + "jsonType.label": "String" + } + }, + { + "id": "5ca62964-2d04-4e8e-963d-e3b08cf32d7c", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "954a5dff-cc19-4dde-b996-787f767db4cc", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "1eba19bf-6fa1-4608-ad2d-d4346580c93d", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "e7bdd267-fcce-451f-b3e1-a775cf611dd2", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "a9a8918c-af00-48a5-a8b3-a28a83653f71", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "cd725067-b6ba-42f1-a940-97a16a23cb85", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "a4e1812c-4093-4666-a6b3-03c5d9b5ca9f", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "d6690292-74d1-48ac-855d-2f0f3799829e", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "ce8f1215-0462-4e87-8a3b-18488aee0267", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0ce95430-80aa-4dd6-994b-5a67302ba531", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "8da0d3b1-d609-417e-9adc-1de77549baf9", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "f89a9158-7c03-49b0-8a3c-d0b75e2ce1b4", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "fb109597-e31e-46d7-84c5-62e5fcf32ac8", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "qb109597-e31e-46d7-7844-62e5fcf32ac8", + "name": "email sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "sub", + "jsonType.label": "String" + } + }, + { + "id": "61c135e5-2447-494b-bc70-9612f383be27", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": ["jboss-logging"], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "74dffa9a-5d4f-4ce3-9708-885212f56861", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "48096073-ceae-4e68-a15b-f1aa390dcce5", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "51b0e87c-ee04-4664-a299-f8e49cb7a9ac", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": ["200"] + } + }, + { + "id": "6379b091-2289-4fe7-894c-c03f1bd0e69b", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "97ae8320-a439-463b-817e-05bd4a6c39d1", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "49131ffc-4831-4e3e-a466-f9f08aa1bee0", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "e12647d2-e21f-49bc-a8c6-28154c5544d2", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-property-mapper", + "saml-user-attribute-mapper", + "oidc-address-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "oidc-full-name-mapper", + "saml-role-list-mapper", + "oidc-usermodel-attribute-mapper" + ] + } + }, + { + "id": "c9f00ef2-00d9-44bd-9b6c-3b3bf57e44ba", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] + } + } + ], + "org.keycloak.userprofile.UserProfileProvider": [ + { + "id": "96260850-72a5-4b49-b96b-5a33d0b5337d", + "providerId": "declarative-user-profile", + "subComponents": {}, + "config": {} + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "55d93b4d-fe05-46a1-a832-36f380aaddf7", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + }, + { + "id": "bee288b4-ecdf-4ec4-8c31-ee330f1e8f95", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": ["100"], + "algorithm": ["HS256"] + } + }, + { + "id": "2aa8f54d-8b4b-4eb7-a05b-89211f544358", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": ["100"], + "algorithm": ["RSA-OAEP"] + } + }, + { + "id": "23ad48f4-2275-4a0d-aa0d-1e0691f9c620", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "0c349304-21fd-47ff-8dc6-46efb107b7e9", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "cf1ed416-7274-4804-88bf-4261b0bacdc6", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "basic-auth-otp", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "d949f1f1-4622-49ec-b74a-4b8a58c653d2", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "3deb6d9d-2064-410c-af99-b1601cd9b1c4", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "f777c4be-f7d1-453e-a9d7-a2a235b7975b", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "1bc12f49-e2ef-42bd-959a-0983e1cd4d65", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "324cdcf5-8f31-4768-9db9-63208f182b39", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "23d17138-8ebd-4195-91d3-614094f62070", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "61fec72a-bfd2-42e8-95c1-fa0b76c1cd2b", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "dc00b9a8-fc37-4591-a1ea-07c7f884d394", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "4f27245a-49b8-4870-a5e2-f0ea624a792c", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "5b2c66e1-7bbf-4707-9db8-244269b68164", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "4bcddec4-4260-4f4f-a757-3aff9b1d30f3", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "04a94e38-b7fb-48f6-8d63-5640f835c619", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "bfcf5112-96ac-485a-8663-b02ad41af919", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "e262d10d-ad0d-4d18-bc05-3a44f7d21736", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Authentication Options", + "userSetupAllowed": false + } + ] + }, + { + "id": "b671c4b3-22b6-4aac-a1d1-464a2101767c", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "f570e064-0e62-4eae-8087-8b06751b8f33", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-profile-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "07124099-1d10-4148-ac06-4b0b700908da", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "0a5fa089-f987-4903-9170-36565edda152", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "d2818365-2189-4003-9817-0ad5368e37f3", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "72508559-0176-4eee-a77e-0795d652be12", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "CONFIGURE_RECOVERY_AUTHN_CODES", + "name": "Recovery Authentication Codes", + "providerId": "CONFIGURE_RECOVERY_AUTHN_CODES", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "UPDATE_EMAIL", + "name": "Update Email", + "providerId": "UPDATE_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaExpiresIn": "120", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DeviceCodeLifespan": "600", + "oauth2DevicePollingInterval": "5", + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false" + }, + "keycloakVersion": "20.0.1", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } + } +] diff --git a/docker/davical/Dockerfile b/docker/davical/Dockerfile new file mode 100644 index 0000000..11c91a0 --- /dev/null +++ b/docker/davical/Dockerfile @@ -0,0 +1,39 @@ +# DAViCal CalDAV Server +# Based on Debian with Apache and PHP +FROM debian:bookworm-slim + +ENV DEBIAN_FRONTEND=noninteractive + +# Install dependencies +RUN apt-get update && apt-get install -y \ + apache2 \ + libapache2-mod-php \ + php-pgsql \ + php-xml \ + php-curl \ + php-imap \ + php-ldap \ + davical \ + postgresql-client \ + && rm -rf /var/lib/apt/lists/* + +# Enable required Apache modules +RUN a2enmod rewrite + +# Copy Apache configuration +COPY davical.conf /etc/apache2/sites-available/davical.conf +RUN a2dissite 000-default && a2ensite davical + +# Copy DAViCal configuration +COPY config.php /etc/davical/config.php + +# Copy and setup entrypoint +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Set permissions +RUN chown -R www-data:www-data /var/log/apache2 + +EXPOSE 80 + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker/davical/config.php b/docker/davical/config.php new file mode 100644 index 0000000..a5f646f --- /dev/null +++ b/docker/davical/config.php @@ -0,0 +1,64 @@ +pg_connect[] = 'host=' . getenv('PGHOST') . ' port=' . (getenv('PGPORT') ?: '5432') . ' dbname=' . getenv('PGDATABASE') . ' user=' . getenv('PGUSER') . ' password=' . getenv('PGPASSWORD'); + +// System name +$c->system_name = 'Calendars DAViCal Server'; + +// Admin email +$c->admin_email = 'admin@example.com'; + +// Allow public access for CalDAV discovery +$c->public_freebusy_url = true; + +// Default locale +$c->default_locale = 'en_US.UTF-8'; + +// Logging - enable for debugging authentication issues +$c->log_caldav_queries = true; + +// Trust proxy headers for auth +$c->trust_x_forwarded = true; + +// Configure base path when behind reverse proxy +// Override SCRIPT_NAME so DAViCal generates correct URLs +// DAViCal uses $_SERVER['SCRIPT_NAME'] to determine the base path for URLs +// We set it to the proxy path WITHOUT /caldav.php since DAViCal will add that itself +if (isset($_SERVER['HTTP_X_FORWARDED_PREFIX'])) { + $_SERVER['SCRIPT_NAME'] = rtrim($_SERVER['HTTP_X_FORWARDED_PREFIX'], '/'); +} elseif (isset($_SERVER['HTTP_X_SCRIPT_NAME'])) { + $_SERVER['SCRIPT_NAME'] = rtrim($_SERVER['HTTP_X_SCRIPT_NAME'], '/'); +} + +// Custom authentication function to use X-Forwarded-User header +// This function is called by DAViCal's authentication system +function authenticate_via_forwarded_user( $username, $password ) { + // Check if X-Forwarded-User header is present + if (isset($_SERVER['HTTP_X_FORWARDED_USER'])) { + $forwarded_user = trim($_SERVER['HTTP_X_FORWARDED_USER']); + + // If the username from Basic Auth matches X-Forwarded-User, authenticate + // Users with password '*' are externally authenticated + if (strtolower($username) === strtolower($forwarded_user)) { + // Return the username to authenticate as this user + // DAViCal will check if user exists and has password '*' + return $forwarded_user; + } + } + + // Fall back to standard authentication + return false; +} + +// Use custom authentication hook +$c->authenticate_hook = array( + 'call' => 'authenticate_via_forwarded_user', + 'config' => array() +); diff --git a/docker/davical/davical.conf b/docker/davical/davical.conf new file mode 100644 index 0000000..fab6fe8 --- /dev/null +++ b/docker/davical/davical.conf @@ -0,0 +1,22 @@ + + ServerName localhost + DocumentRoot /usr/share/davical/htdocs + DirectoryIndex index.php + + Alias /images/ /usr/share/davical/htdocs/images/ + + + AllowOverride All + Require all granted + + + AcceptPathInfo On + + # CalDAV principal URL + RewriteEngine On + RewriteRule ^/caldav/(.*)$ /caldav.php/$1 [L] + RewriteRule ^/\.well-known/caldav /caldav.php [R=301,L] + + ErrorLog ${APACHE_LOG_DIR}/davical_error.log + CustomLog ${APACHE_LOG_DIR}/davical_access.log combined + diff --git a/docker/davical/run-migrations b/docker/davical/run-migrations new file mode 100755 index 0000000..8caef0f --- /dev/null +++ b/docker/davical/run-migrations @@ -0,0 +1,93 @@ +#!/bin/bash +### +# Run DB migrations necessary to use Davical. +# Will create the database on first-run, and only run necessary migrations on subsequent runs. +# +# Requires the following environment variables in addition to the container variables. +# - ROOT_PGUSER +# - ROOT_PGPASSWORD +# - DAVICAL_ADMIN_PASS +### + +set -e + +if [ -z ${ROOT_PGUSER+x} ]; then + echo "ROOT_PGUSER must be set" + exit 1 +fi +if [ -z ${ROOT_PGPASSWORD+x} ]; then + echo "ROOT_PGPASSWORD must be set" + exit 1 +fi +if [ -z ${DAVICAL_ADMIN_PASS+x} ]; then + echo "DAVICAL_ADMIN_PASS must be set" + exit 1 +fi + +if [ -z ${DBA_PGPASSWORD+x} ]; then + DBA_PGPASSWORD=$PGPASSWORD +fi + +if [ -z ${DAVICAL_SCHEMA+x} ]; then + DAVICAL_SCHEMA=$DBA_PGUSER +fi + +# store PG environment so it can be overridden as-needed +DAVICAL_PGUSER=$PGUSER +DAVICAL_PGPASSWORD=$PGPASSWORD +DAVICAL_PGDATABASE=$PGDATABASE + +run_migrations() { + echo "Running dba/update-davical-database, which should automatically apply any necessary DB migrations." + /usr/share/davical/dba/update-davical-database \ + --dbname $DAVICAL_PGDATABASE \ + --dbuser $DBA_PGUSER \ + --dbhost $PGHOST \ + --dbpass $DBA_PGPASSWORD \ + --appuser $DAVICAL_PGUSER \ + --owner $DBA_PGUSER +} + +export PGUSER=$ROOT_PGUSER +export PGPASSWORD=$ROOT_PGPASSWORD +export PGDATABASE= + +# Wait for PG connection +retries=10 +until pg_isready -q -t 3; do + [[ retries -eq 0 ]] && echo "Could not connect to Postgres" && exit 1 + echo "Waiting for Postgres to be available" + retries=$((retries-1)) + sleep 1 +done + +# Check whether the database has already been setup, with awl tables. +tables=$(psql -d $DAVICAL_PGDATABASE -c "\\dt") +if echo "$tables" | grep -q "awl_db_revision"; then + # The database already exists - just run any outstanding migrations + run_migrations + exit 0 +fi + +echo "Database has not been created - running first-time database setup" + +# the rest of the commands are run as the dba superuser +export PGUSER=$DBA_PGUSER +export PGPASSWORD=$DBA_PGPASSWORD +export PGDATABASE=$DAVICAL_PGDATABASE + +psql -qXAt -f /usr/share/awl/dba/awl-tables.sql +psql -qXAt -f /usr/share/awl/dba/schema-management.sql +psql -qXAt -f /usr/share/davical/dba/davical.sql +run_migrations +psql -qXAt -f /usr/share/davical/dba/base-data.sql + +# DAViCal only uses salted SHA1 at-best, but it's better than storing the password in plaintext! +# see https://wiki.davical.org/index.php?title=Force_Admin_Password +# from https://gitlab.com/davical-project/awl/-/blob/3f044e2dc8435c2eeba61a3c41ec11c820711ab3/inc/DataUpdate.php#L48-58 +salted_password=$(php -r 'require "/usr/share/awl/inc/AWLUtilities.php"; echo session_salted_sha1($argv[1]);' "$DAVICAL_ADMIN_PASS") +psql -qX \ + -v pw="'$salted_password'" \ + <() " +""" +from __future__ import unicode_literals + +import re + +import requests + +from gitlint.rules import CommitMessageTitle, LineRule, RuleViolation + + +class GitmojiTitle(LineRule): + """ + This rule will enforce that each commit title is of the form "() " + where gitmoji is an emoji from the list defined in https://gitmoji.carloscuesta.me and + subject should be all lowercase + """ + + id = "UC1" + name = "title-should-have-gitmoji-and-scope" + target = CommitMessageTitle + + def validate(self, title, _commit): + """ + Download the list possible gitmojis from the project's github repository and check that + title contains one of them. + """ + gitmojis = requests.get( + "https://raw.githubusercontent.com/carloscuesta/gitmoji/master/packages/gitmojis/src/gitmojis.json" + ).json()["gitmojis"] + emojis = [item["emoji"] for item in gitmojis] + pattern = r"^({:s})\(.*\)\s[a-zA-Z].*$".format("|".join(emojis)) + if not re.search(pattern, title): + violation_msg = 'Title does not match regex "() "' + return [RuleViolation(self.id, violation_msg, title)] diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..edf8b11 --- /dev/null +++ b/renovate.json @@ -0,0 +1,25 @@ +{ + "extends": ["github>numerique-gouv/renovate-configuration"], + "dependencyDashboard": true, + "labels": ["dependencies", "noChangeLog"], + "packageRules": [ + { + "groupName": "allowed redis versions", + "matchManagers": ["pep621"], + "matchPackageNames": ["redis"], + "allowedVersions": "<6.0.0" + }, + { + "groupName": "allowed pylint versions", + "matchManagers": ["pep621"], + "matchPackageNames": ["pylint"], + "allowedVersions": "<4.0.0" + }, + { + "description": "Disable requires-python updates - managed manually", + "matchManagers": ["pep621"], + "matchPackageNames": ["python"], + "enabled": false + } + ] +} \ No newline at end of file diff --git a/src/backend/.dockerignore b/src/backend/.dockerignore new file mode 100644 index 0000000..e4b67e7 --- /dev/null +++ b/src/backend/.dockerignore @@ -0,0 +1,33 @@ +# Python +__pycache__ +*.pyc +**/__pycache__ +**/*.pyc +venv +.venv + +# System-specific files +.DS_Store +**/.DS_Store + +# Docker +compose.* +env.d + +# Docs +docs +*.md +*.log + +# Development/test cache & configurations +data +.cache +.circleci +.git +.vscode +.iml +.idea +db.sqlite3 +.mypy_cache +.pylint.d +.pytest_cache diff --git a/src/backend/.pylintrc b/src/backend/.pylintrc new file mode 100644 index 0000000..1aeec30 --- /dev/null +++ b/src/backend/.pylintrc @@ -0,0 +1,472 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=migrations + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs=0 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins=pylint_django,pylint.extensions.no_self_use + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=bad-inline-option, + deprecated-pragma, + django-not-configured, + file-ignored, + locally-disabled, + no-self-use, + raw-checker-failed, + suppressed-message, + useless-suppression + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=c-extension-no-member + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=optparse.Values,sys.exit + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local,responses, + Template,Contact + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(#\s*)??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=yes + +# Minimum lines number of a similarity. +# First implementations of CMS wizards have common fields we do not want to factorize for now +min-similarity-lines=35 + + +[BASIC] + +# Naming style matching correct argument names +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style +#argument-rgx= + +# Naming style matching correct attribute names +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Naming style matching correct class attribute names +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style +#class-attribute-rgx= + +# Naming style matching correct class names +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming-style +#class-rgx= + +# Naming style matching correct constant names +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__)|urlpatterns|logger)$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma +good-names=i, + j, + k, + cm, + ex, + Run, + _ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming style matching correct inline iteration names +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style +#inlinevar-rgx= + +# Naming style matching correct method names +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style +method-rgx=([a-z_][a-z0-9_]{2,50}|setUp|set[Uu]pClass|tearDown|tear[Dd]ownClass|assert[A-Z]\w*|maxDiff|test_[a-z0-9_]+)$ + +# Naming style matching correct module names +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style +#variable-rgx= + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=20 + +# Maximum number of parents for a class (see R0901). +max-parents=10 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=0 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=builtins.Exception diff --git a/src/backend/Dockerfile b/src/backend/Dockerfile new file mode 100644 index 0000000..059c691 --- /dev/null +++ b/src/backend/Dockerfile @@ -0,0 +1,158 @@ +# Django calendars + +# ---- base image to inherit from ---- +FROM python:3.13.9-alpine AS base + +# Upgrade pip to its latest release to speed up dependencies installation +# We must do taht to avoid having an outdated pip version with security issues +RUN python -m pip install --upgrade pip setuptools + +# Upgrade system packages to install security updates +RUN apk update && \ + apk upgrade && \ + apk add git + +# ---- Back-end builder image ---- +FROM base AS back-builder + +ENV UV_COMPILE_BYTECODE=1 +ENV UV_LINK_MODE=copy + +# Disable Python downloads, because we want to use the system interpreter +# across both images. If using a managed Python version, it needs to be +# copied from the build image into the final image; +ENV UV_PYTHON_DOWNLOADS=0 + +# install uv +COPY --from=ghcr.io/astral-sh/uv:0.9.10 /uv /uvx /bin/ + +WORKDIR /app + + +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --locked --no-install-project --no-dev +COPY . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --locked --no-dev + +# ---- static link collector ---- +FROM base AS link-collector +ARG CALENDARS_STATIC_ROOT=/data/static + +# Install pango & rdfind +RUN apk add \ + pango \ + rdfind + +WORKDIR /app + +# Copy the application from the builder +COPY --from=back-builder /app /app + +ENV PATH="/app/.venv/bin:$PATH" + + +# collectstatic +RUN DJANGO_CONFIGURATION=Build \ + python manage.py collectstatic --noinput + +# Replace duplicated file by a symlink to decrease the overall size of the +# final image +RUN rdfind -makesymlinks true -followsymlinks true -makeresultsfile false ${CALENDARS_STATIC_ROOT} + +# ---- Core application image ---- +FROM base AS core + +ENV PYTHONUNBUFFERED=1 + +# Install required system libs +RUN apk add \ + cairo \ + file \ + font-noto \ + font-noto-emoji \ + gettext \ + gdk-pixbuf \ + libffi-dev \ + pandoc \ + pango \ + shared-mime-info + +RUN wget https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types -O /etc/mime.types + +# Give the "root" group the same permissions as the "root" user on /etc/passwd +# to allow a user belonging to the root group to add new users; typically the +# docker user (see entrypoint). +RUN chmod g=u /etc/passwd + +# Copy the application from the builder +COPY --from=back-builder /app /app + +WORKDIR /app + +ENV PATH="/app/.venv/bin:$PATH" + +# Generate compiled translation messages +RUN DJANGO_CONFIGURATION=Build \ + python manage.py compilemessages --ignore=".venv/**/*" + + +# We wrap commands run in this container by the following entrypoint that +# creates a user on-the-fly with the container user ID (see USER) and root group +# ID. +ENTRYPOINT [ "/app/entrypoint" ] + +# ---- Development image ---- +FROM core AS backend-development + +# Switch back to the root user to install development dependencies +USER root:root + +# Install psql +RUN apk add postgresql-client + +# Install uv for development dependencies +COPY --from=ghcr.io/astral-sh/uv:0.9.10 /uv /uvx /bin/ + +# Install development dependencies (ensure venv is created and used) +RUN uv sync --all-extras --locked + +# Ensure venv is accessible and PATH is set +ENV PATH="/app/.venv/bin:$PATH" +ENV VIRTUAL_ENV="/app/.venv" + +# Restore the un-privileged user running the application +ARG DOCKER_USER +USER ${DOCKER_USER} + +# Target database host (e.g. database engine following docker compose services +# name) & port +ENV DB_HOST=postgresql \ + DB_PORT=5432 + +# Run django development server +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] + +# ---- Production image ---- +FROM core AS backend-production + +ARG CALENDARS_STATIC_ROOT=/data/static + +# Remove git, we don't need it in the production image +RUN apk del git + +# Gunicorn +RUN mkdir -p /usr/local/etc/gunicorn +COPY docker/files/usr/local/etc/gunicorn/calendars.py /usr/local/etc/gunicorn/calendars.py + +# Un-privileged user running the application +ARG DOCKER_USER +USER ${DOCKER_USER} + +# Copy statics +COPY --from=link-collector ${CALENDARS_STATIC_ROOT} ${CALENDARS_STATIC_ROOT} + +# The default command runs gunicorn WSGI server in calendars' main module +CMD ["gunicorn", "-c", "/app/gunicorn.conf.py", "calendars.wsgi:application"] diff --git a/src/backend/MANIFEST.in b/src/backend/MANIFEST.in new file mode 100644 index 0000000..4a8db10 --- /dev/null +++ b/src/backend/MANIFEST.in @@ -0,0 +1,3 @@ +include LICENSE +include README.md +recursive-include src/backend/calendars *.html *.png *.gif *.css *.ico *.jpg *.jpeg *.po *.mo *.eot *.svg *.ttf *.woff *.woff2 diff --git a/src/backend/__init__.py b/src/backend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/calendars/__init__.py b/src/backend/calendars/__init__.py new file mode 100644 index 0000000..9cca34c --- /dev/null +++ b/src/backend/calendars/__init__.py @@ -0,0 +1,5 @@ +"""Calendars package. Import the celery app early to load shared task form dependencies.""" + +from .celery_app import app as celery_app + +__all__ = ["celery_app"] diff --git a/src/backend/calendars/celery_app.py b/src/backend/calendars/celery_app.py new file mode 100644 index 0000000..7b0f82b --- /dev/null +++ b/src/backend/calendars/celery_app.py @@ -0,0 +1,26 @@ +"""Calendars celery configuration file.""" + +import os + +from celery import Celery +from configurations.importer import install + +# Set the default Django settings module for the 'celery' program. +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "calendars.settings") +os.environ.setdefault("DJANGO_CONFIGURATION", "Development") + +install(check_options=True) + +# Can be loaded only after install call. +from django.conf import settings # pylint: disable=wrong-import-position + +app = Celery("calendars") + +# Using a string here means the worker doesn't have to serialize +# the configuration object to child processes. +# - namespace='CELERY' means all celery-related configuration keys +# should have a `CELERY_` prefix. +app.config_from_object("django.conf:settings", namespace="CELERY") + +# Load task modules from all registered Django apps. +app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) diff --git a/src/backend/calendars/configuration/theme/default.json b/src/backend/calendars/configuration/theme/default.json new file mode 100644 index 0000000..1c5165f --- /dev/null +++ b/src/backend/calendars/configuration/theme/default.json @@ -0,0 +1,69 @@ +{ + "footer": { + "default": { + "externalLinks": [ + { + "label": "Github", + "href": "https://github.com/suitenumerique/calendars/" + }, + { + "label": "ANCT", + "href": "https://anct.gouv.fr/" + } + ], + "license": { + "label": "Unless otherwise stated, all content on this site is under", + "link": { + "label": "licence etalab-2.0", + "href": "https://github.com/etalab/licence-ouverte/blob/master/LO.md" + } + } + }, + "en": { + "legalLinks": [ + { + "label": "Legal Notice", + "href": "#" + }, + { + "label": "Personal data and cookies", + "href": "#" + }, + { + "label": "Accessibility: non compliant", + "href": "#" + } + ], + "license": { + "label": "Unless otherwise stated, all content on this site is under", + "link": { + "label": "licence etalab-2.0", + "href": "https://github.com/etalab/licence-ouverte/blob/master/LO.md" + } + } + }, + "fr": { + "legalLinks": [ + { + "label": "Mentions légales", + "href": "#" + }, + { + "label": "Données personnelles et cookies", + "href": "#" + }, + { + "label": "Accessibilité: non conforme", + "href": "#" + } + ], + "license": { + "label": "Sauf mention contraire, tout le contenu de ce site est sous", + "link": { + "label": "licence etalab-2.0", + "href": "https://github.com/etalab/licence-ouverte/blob/master/LO.md" + } + } + } + } +} diff --git a/src/backend/calendars/settings.py b/src/backend/calendars/settings.py new file mode 100755 index 0000000..a489afe --- /dev/null +++ b/src/backend/calendars/settings.py @@ -0,0 +1,919 @@ +""" +Django settings for calendar project. + +Generated by 'django-admin startproject' using Django 3.1.5. + +For more information on this file, see +https://docs.djangoproject.com/en/3.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.1/ref/settings/ +""" + +import os +import tomllib +from socket import gethostbyname, gethostname + +from django.utils.translation import gettext_lazy as _ + +import dj_database_url +import sentry_sdk +from configurations import Configuration, values +from lasuite.configuration.values import SecretFileValue +from sentry_sdk.integrations.django import DjangoIntegration + +# pylint: disable=too-many-lines + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +DATA_DIR = os.environ.get("DATA_DIR", os.path.join("/", "data")) + + +def get_release(): + """ + Get the current release of the application + """ + try: + with open(os.path.join(BASE_DIR, "pyproject.toml"), "rb") as f: + pyproject_data = tomllib.load(f) + return pyproject_data["project"]["version"] + except (FileNotFoundError, KeyError): + return "NA" # Default: not available + + +class Base(Configuration): + """ + This is the base configuration every configuration (aka environment) should inherit from. It + is recommended to configure third-party applications by creating a configuration mixins in + ./configurations and compose the Base configuration with those mixins. + + It depends on an environment variable that SHOULD be defined: + + * DJANGO_SECRET_KEY + + You may also want to override default configuration by setting the following environment + variables: + + * SENTRY_DSN + * DB_NAME + * DB_HOST + * DB_PASSWORD + * DB_USER + """ + + DEBUG = False + LOAD_E2E_URLS = False + USE_SWAGGER = False + + API_VERSION = "v1.0" + + # DAViCal CalDAV server URL + DAVICAL_URL = values.Value( + "http://davical:80", environ_name="DAVICAL_URL", environ_prefix=None + ) + + # Security + ALLOWED_HOSTS = values.ListValue([]) + SECRET_KEY = SecretFileValue(None) + SERVER_TO_SERVER_API_TOKENS = values.ListValue([]) + + # Application definition + ROOT_URLCONF = "calendars.urls" + WSGI_APPLICATION = "calendars.wsgi.application" + + # Database + DATABASES = { + "default": dj_database_url.config() + if os.environ.get("DATABASE_URL") + else { + "ENGINE": values.Value( + "django.db.backends.postgresql", + environ_name="DB_ENGINE", + environ_prefix=None, + ), + "NAME": values.Value( + "calendars", environ_name="DB_NAME", environ_prefix=None + ), + "USER": values.Value("pgroot", environ_name="DB_USER", environ_prefix=None), + "PASSWORD": SecretFileValue( + "pass", environ_name="DB_PASSWORD", environ_prefix=None + ), + "HOST": values.Value( + "localhost", environ_name="DB_HOST", environ_prefix=None + ), + "PORT": values.Value(5432, environ_name="DB_PORT", environ_prefix=None), + } + } + DEFAULT_AUTO_FIELD = "django.db.models.AutoField" + + # Static files (CSS, JavaScript, Images) + STATIC_URL = "/static/" + STATIC_ROOT = os.path.join(DATA_DIR, "static") + MEDIA_URL = "/media/" + MEDIA_URL_PREVIEW = "/media/preview/" + MEDIA_ROOT = os.path.join(DATA_DIR, "media") + MEDIA_BASE_URL = values.Value( + None, environ_name="MEDIA_BASE_URL", environ_prefix=None + ) + + SITE_ID = 1 + + STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": values.Value( + "whitenoise.storage.CompressedManifestStaticFilesStorage", + environ_name="STORAGES_STATICFILES_BACKEND", + ), + }, + } + + # Maximum size of the request body in memory. + # This is used to limit the size of the request body in memory. + # This also limits the size of the file that can be uploaded to the server. + DATA_UPLOAD_MAX_MEMORY_SIZE = values.PositiveIntegerValue( + 2 * (2**30), # 2GB + environ_name="DATA_UPLOAD_MAX_MEMORY_SIZE", + environ_prefix=None, + ) + + # Internationalization + # https://docs.djangoproject.com/en/3.1/topics/i18n/ + + # Languages + LANGUAGE_CODE = values.Value("en-us") + LANGUAGE_COOKIE_NAME = "calendar_language" # cookie & language is set from frontend + + DRF_NESTED_MULTIPART_PARSER = { + # output of parser is converted to querydict + # if is set to False, dict python is returned + "querydict": False, + } + + # Careful! Languages should be ordered by priority, as this tuple is used to get + # fallback/default languages throughout the app. + LANGUAGES = values.SingleNestedTupleValue( + ( + ("en-us", _("English")), + ("fr-fr", _("French")), + ("de-de", _("German")), + ("nl-nl", _("Dutch")), + ) + ) + + LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),) + + TIME_ZONE = "UTC" + USE_I18N = True + USE_TZ = True + + # Templates + TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [os.path.join(BASE_DIR, "templates")], + "OPTIONS": { + "context_processors": [ + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "django.template.context_processors.csrf", + "django.template.context_processors.debug", + "django.template.context_processors.i18n", + "django.template.context_processors.media", + "django.template.context_processors.request", + "django.template.context_processors.tz", + ], + "loaders": [ + "django.template.loaders.filesystem.Loader", + "django.template.loaders.app_directories.Loader", + ], + }, + }, + ] + + MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.locale.LocaleMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "corsheaders.middleware.CorsMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + ] + + AUTHENTICATION_BACKENDS = [ + "django.contrib.auth.backends.ModelBackend", + "core.authentication.backends.OIDCAuthenticationBackend", + ] + + # Django applications from the highest priority to the lowest + INSTALLED_APPS = [ + "core", + "drf_spectacular", + "drf_standardized_errors", + # Third party apps + "corsheaders", + "django_celery_beat", + "django_filters", + "rest_framework", + "rest_framework_api_key", + "parler", + # Django + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.postgres", + "django.contrib.sessions", + "django.contrib.sites", + "django.contrib.messages", + "django.contrib.staticfiles", + # OIDC third party + "mozilla_django_oidc", + ] + + # Cache + CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": values.Value( + "redis://redis:6379/0", + environ_name="REDIS_URL", + environ_prefix=None, + ), + "TIMEOUT": values.IntegerValue( + 30, # timeout in seconds + environ_name="CACHES_DEFAULT_TIMEOUT", + environ_prefix=None, + ), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, + "KEY_PREFIX": values.Value( + "calendar", + environ_name="CACHES_DEFAULT_KEY_PREFIX", + environ_prefix=None, + ), + }, + "session": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": values.Value( + "redis://redis:6379/0", + environ_name="REDIS_URL", + environ_prefix=None, + ), + "TIMEOUT": values.IntegerValue( + 30, # timeout in seconds + environ_name="CACHES_SESSION_TIMEOUT", + environ_prefix=None, + ), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, + }, + } + + REST_FRAMEWORK = { + "DEFAULT_AUTHENTICATION_CLASSES": ( + "mozilla_django_oidc.contrib.drf.OIDCAuthentication", + "rest_framework.authentication.SessionAuthentication", + ), + "DEFAULT_PARSER_CLASSES": [ + "rest_framework.parsers.JSONParser", + "nested_multipart_parser.drf.DrfNestedParser", + ], + "DEFAULT_RENDERER_CLASSES": [ + # 🔒️ Disable BrowsableAPIRenderer which provides forms allowing a user to + # see all the data in the database (ie a serializer with a ForeignKey field + # will generate a form with a field with all possible values of the FK). + "rest_framework.renderers.JSONRenderer", + ], + "EXCEPTION_HANDLER": "core.api.exception_handler", + "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination", + "PAGE_SIZE": 20, + "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning", + "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", + "DEFAULT_THROTTLE_CLASSES": ["rest_framework.throttling.ScopedRateThrottle"], + "DEFAULT_THROTTLE_RATES": { + "user_list_sustained": values.Value( + default="180/hour", + environ_name="API_USERS_LIST_THROTTLE_RATE_SUSTAINED", + environ_prefix=None, + ), + "user_list_burst": values.Value( + default="30/minute", + environ_name="API_USERS_LIST_THROTTLE_RATE_BURST", + environ_prefix=None, + ), + }, + } + + MAX_PAGE_SIZE = values.PositiveIntegerValue( + 200, environ_name="MAX_PAGE_SIZE", environ_prefix=None + ) + + SPECTACULAR_SETTINGS = { + "TITLE": "calendar API", + "DESCRIPTION": "This is the calendar API schema.", + "VERSION": "1.0.0", + "SERVE_INCLUDE_SCHEMA": False, + "ENABLE_DJANGO_DEPLOY_CHECK": values.BooleanValue( + default=False, + environ_name="SPECTACULAR_SETTINGS_ENABLE_DJANGO_DEPLOY_CHECK", + ), + "COMPONENT_SPLIT_REQUEST": True, + # OTHER SETTINGS + "SWAGGER_UI_DIST": "SIDECAR", # shorthand to use the sidecar instead + "SWAGGER_UI_FAVICON_HREF": "SIDECAR", + "REDOC_DIST": "SIDECAR", + } + + TRASHBIN_CUTOFF_DAYS = values.Value( + 30, environ_name="TRASHBIN_CUTOFF_DAYS", environ_prefix=None + ) + + AUTH_USER_MODEL = "core.User" + INVITATION_VALIDITY_DURATION = 604800 # 7 days, in seconds + + # CORS + CORS_ALLOW_CREDENTIALS = True + CORS_ALLOW_ALL_ORIGINS = values.BooleanValue(False) + CORS_ALLOWED_ORIGINS = values.ListValue([]) + CORS_ALLOWED_ORIGIN_REGEXES = values.ListValue([]) + # Allow CalDAV methods (PROPFIND, REPORT, etc.) + CORS_ALLOW_METHODS = [ + "DELETE", + "GET", + "OPTIONS", + "PATCH", + "POST", + "PUT", + "PROPFIND", + "REPORT", + "MKCOL", + "MKCALENDAR", + ] + # Allow CalDAV headers (case-sensitive for CORS preflight) + CORS_ALLOW_HEADERS = [ + "accept", + "accept-encoding", + "authorization", + "content-type", + "dnt", + "origin", + "user-agent", + "x-csrftoken", + "x-requested-with", + "depth", # CalDAV header (lowercase as sent by browsers) + "if-match", + "if-none-match", + "prefer", + ] + + # Sentry + SENTRY_DSN = values.Value(None, environ_name="SENTRY_DSN", environ_prefix=None) + + # Frontend + FRONTEND_THEME = values.Value( + None, environ_name="FRONTEND_THEME", environ_prefix=None + ) + FRONTEND_MORE_LINK = values.Value( + None, + environ_name="FRONTEND_MORE_LINK", + environ_prefix=None, + ) + FRONTEND_FEEDBACK_BUTTON_SHOW = values.BooleanValue( + default=False, environ_name="FRONTEND_FEEDBACK_BUTTON_SHOW", environ_prefix=None + ) + # For instance, you might want to bind this button to an external library to trigger survey instead of the build in feedback modal. + FRONTEND_FEEDBACK_BUTTON_IDLE = values.BooleanValue( + default=False, environ_name="FRONTEND_FEEDBACK_BUTTON_IDLE", environ_prefix=None + ) + FRONTEND_FEEDBACK_ITEMS = values.DictValue( + {}, environ_name="FRONTEND_FEEDBACK_ITEMS", environ_prefix=None + ) + FRONTEND_FEEDBACK_MESSAGES_WIDGET_ENABLED = values.BooleanValue( + default=False, + environ_name="FRONTEND_FEEDBACK_MESSAGES_WIDGET_ENABLED", + environ_prefix=None, + ) + FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL = values.Value( + None, + environ_name="FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL", + environ_prefix=None, + ) + FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL = values.Value( + None, + environ_name="FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL", + environ_prefix=None, + ) + FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH = values.Value( + None, environ_name="FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH", environ_prefix=None + ) + FRONTEND_HIDE_GAUFRE = values.BooleanValue( + default=False, environ_name="FRONTEND_HIDE_GAUFRE", environ_prefix=None + ) + THEME_CUSTOMIZATION_FILE_PATH = values.Value( + os.path.join(BASE_DIR, "calendars/configuration/theme/default.json"), + environ_name="THEME_CUSTOMIZATION_FILE_PATH", + environ_prefix=None, + ) + THEME_CUSTOMIZATION_CACHE_TIMEOUT = values.Value( + 60 * 60 * 24, + environ_name="THEME_CUSTOMIZATION_CACHE_TIMEOUT", + environ_prefix=None, + ) + + # Easy thumbnails + THUMBNAIL_EXTENSION = "webp" + THUMBNAIL_TRANSPARENCY_EXTENSION = "webp" + THUMBNAIL_DEFAULT_STORAGE_ALIAS = "default" + THUMBNAIL_ALIASES = {} + + # Celery + CELERY_BROKER_URL = values.Value("redis://redis:6379/0") + CELERY_BROKER_TRANSPORT_OPTIONS = values.DictValue({}) + CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" + + # Session + SESSION_ENGINE = "django.contrib.sessions.backends.cache" + SESSION_CACHE_ALIAS = "session" + SESSION_COOKIE_AGE = 60 * 60 * 12 + + # OIDC - Authorization Code Flow + OIDC_CREATE_USER = values.BooleanValue( + default=True, + environ_name="OIDC_CREATE_USER", + ) + OIDC_CALLBACK_CLASS = "core.authentication.views.OIDCAuthenticationCallbackView" + OIDC_RP_SIGN_ALGO = values.Value( + "RS256", environ_name="OIDC_RP_SIGN_ALGO", environ_prefix=None + ) + OIDC_RP_CLIENT_ID = values.Value( + "calendar", environ_name="OIDC_RP_CLIENT_ID", environ_prefix=None + ) + OIDC_RP_CLIENT_SECRET = SecretFileValue( + None, + environ_name="OIDC_RP_CLIENT_SECRET", + environ_prefix=None, + ) + OIDC_OP_JWKS_ENDPOINT = values.Value( + environ_name="OIDC_OP_JWKS_ENDPOINT", environ_prefix=None + ) + OIDC_OP_AUTHORIZATION_ENDPOINT = values.Value( + environ_name="OIDC_OP_AUTHORIZATION_ENDPOINT", environ_prefix=None + ) + OIDC_OP_TOKEN_ENDPOINT = values.Value( + None, environ_name="OIDC_OP_TOKEN_ENDPOINT", environ_prefix=None + ) + OIDC_OP_USER_ENDPOINT = values.Value( + None, environ_name="OIDC_OP_USER_ENDPOINT", environ_prefix=None + ) + OIDC_OP_LOGOUT_ENDPOINT = values.Value( + None, environ_name="OIDC_OP_LOGOUT_ENDPOINT", environ_prefix=None + ) + OIDC_REDIRECT_FIELD_NAME = values.Value( + "returnTo", environ_name="OIDC_REDIRECT_FIELD_NAME", environ_prefix=None + ) + OIDC_AUTH_REQUEST_EXTRA_PARAMS = values.DictValue( + {}, environ_name="OIDC_AUTH_REQUEST_EXTRA_PARAMS", environ_prefix=None + ) + OIDC_RP_SCOPES = values.Value( + "openid email", environ_name="OIDC_RP_SCOPES", environ_prefix=None + ) + LOGIN_REDIRECT_URL = values.Value( + None, environ_name="LOGIN_REDIRECT_URL", environ_prefix=None + ) + LOGIN_REDIRECT_URL_FAILURE = values.Value( + None, environ_name="LOGIN_REDIRECT_URL_FAILURE", environ_prefix=None + ) + LOGOUT_REDIRECT_URL = values.Value( + None, environ_name="LOGOUT_REDIRECT_URL", environ_prefix=None + ) + OIDC_USE_NONCE = values.BooleanValue( + default=True, environ_name="OIDC_USE_NONCE", environ_prefix=None + ) + OIDC_REDIRECT_REQUIRE_HTTPS = values.BooleanValue( + default=False, environ_name="OIDC_REDIRECT_REQUIRE_HTTPS", environ_prefix=None + ) + OIDC_REDIRECT_ALLOWED_HOSTS = values.ListValue( + default=[], environ_name="OIDC_REDIRECT_ALLOWED_HOSTS", environ_prefix=None + ) + OIDC_STORE_ID_TOKEN = values.BooleanValue( + default=True, environ_name="OIDC_STORE_ID_TOKEN", environ_prefix=None + ) + OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION = values.BooleanValue( + default=True, + environ_name="OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION", + environ_prefix=None, + ) + + OIDC_STORE_ACCESS_TOKEN = values.BooleanValue( + default=False, environ_name="OIDC_STORE_ACCESS_TOKEN", environ_prefix=None + ) + OIDC_STORE_REFRESH_TOKEN = values.BooleanValue( + default=False, environ_name="OIDC_STORE_REFRESH_TOKEN", environ_prefix=None + ) + OIDC_STORE_REFRESH_TOKEN_KEY = values.Value( + default=None, + environ_name="OIDC_STORE_REFRESH_TOKEN_KEY", + environ_prefix=None, + ) + + # OIDC claims to store + OIDC_STORE_CLAIMS = values.ListValue( + default=[], + environ_name="OIDC_STORE_CLAIMS", + environ_prefix=None, + ) + + # WARNING: Enabling this setting allows multiple user accounts to share the same email + # address. This may cause security issues and is not recommended for production use when + # email is activated as fallback for identification (see previous setting). + OIDC_ALLOW_DUPLICATE_EMAILS = values.BooleanValue( + default=False, + environ_name="OIDC_ALLOW_DUPLICATE_EMAILS", + environ_prefix=None, + ) + + OIDC_USER_INFO = values.ListValue( + default=values.ListValue( # retrocompatibility + default=[], + environ_name="USER_OIDC_ESSENTIAL_CLAIMS", + environ_prefix=None, + ), + environ_name="OIDC_USER_INFO", + environ_prefix=None, + ) + + OIDC_USERINFO_FULLNAME_FIELDS = values.ListValue( + default=["first_name", "last_name"], + environ_name="OIDC_USERINFO_FULLNAME_FIELDS", + environ_prefix=None, + ) + OIDC_USERINFO_SHORTNAME_FIELD = values.Value( + default="first_name", + environ_name="OIDC_USERINFO_SHORTNAME_FIELD", + environ_prefix=None, + ) + + # OIDC Resource Server + + OIDC_RESOURCE_SERVER_ENABLED = values.BooleanValue( + default=False, environ_name="OIDC_RESOURCE_SERVER_ENABLED", environ_prefix=None + ) + + OIDC_RS_BACKEND_CLASS = values.Value( + "lasuite.oidc_resource_server.backend.ResourceServerBackend", + environ_name="OIDC_RS_BACKEND_CLASS", + environ_prefix=None, + ) + + OIDC_OP_URL = values.Value(None, environ_name="OIDC_OP_URL", environ_prefix=None) + + OIDC_VERIFY_SSL = values.BooleanValue( + default=True, environ_name="OIDC_VERIFY_SSL", environ_prefix=None + ) + + OIDC_TIMEOUT = values.PositiveIntegerValue( + 3, environ_name="OIDC_TIMEOUT", environ_prefix=None + ) + + OIDC_PROXY = values.Value(None, environ_name="OIDC_PROXY", environ_prefix=None) + + OIDC_OP_INTROSPECTION_ENDPOINT = values.Value( + None, environ_name="OIDC_OP_INTROSPECTION_ENDPOINT", environ_prefix=None + ) + + OIDC_RS_CLIENT_ID = values.Value( + None, environ_name="OIDC_RS_CLIENT_ID", environ_prefix=None + ) + + OIDC_RS_CLIENT_SECRET = values.Value( + None, environ_name="OIDC_RS_CLIENT_SECRET", environ_prefix=None + ) + + OIDC_RS_AUDIENCE_CLAIM = values.Value( + "client_id", environ_name="OIDC_RS_AUDIENCE_CLAIM", environ_prefix=None + ) + + OIDC_RS_ENCRYPTION_ENCODING = values.Value( + "A256GCM", environ_name="OIDC_RS_ENCRYPTION_ENCODING", environ_prefix=None + ) + + OIDC_RS_ENCRYPTION_ALGO = values.Value( + "RSA-OAEP", environ_name="OIDC_RS_ENCRYPTION_ALGO", environ_prefix=None + ) + + OIDC_RS_SIGNING_ALGO = values.Value( + "ES256", environ_name="OIDC_RS_SIGNING_ALGO", environ_prefix=None + ) + + OIDC_RS_SCOPES = values.ListValue( + ["openid"], environ_name="OIDC_RS_SCOPES", environ_prefix=None + ) + + OIDC_RS_ALLOWED_AUDIENCES = values.ListValue( + default=[], + environ_name="OIDC_RS_ALLOWED_AUDIENCES", + environ_prefix=None, + ) + + # External API Configuration + # Configure available routes and actions for external_api endpoints + EXTERNAL_API = values.DictValue( + default={ + "users": { + "enabled": True, + "actions": ["get_me"], + }, + }, + environ_name="EXTERNAL_API", + environ_prefix=None, + ) + + OIDC_RS_PRIVATE_KEY_STR = values.Value( + default=None, + environ_name="OIDC_RS_PRIVATE_KEY_STR", + environ_prefix=None, + ) + OIDC_RS_ENCRYPTION_KEY_TYPE = values.Value( + default="RSA", + environ_name="OIDC_RS_ENCRYPTION_KEY_TYPE", + environ_prefix=None, + ) + + ALLOW_LOGOUT_GET_METHOD = values.BooleanValue( + default=True, environ_name="ALLOW_LOGOUT_GET_METHOD", environ_prefix=None + ) + + # Logging + # We want to make it easy to log to console but by default we log production + # to Sentry and don't want to log to console. + LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "simple": { + "format": "{asctime} {name} {levelname} {message}", + "style": "{", + }, + }, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "formatter": "simple", + }, + }, + # Override root logger to send it to console + "root": { + "handlers": ["console"], + "level": values.Value( + "INFO", environ_name="LOGGING_LEVEL_LOGGERS_ROOT", environ_prefix=None + ), + }, + "loggers": { + "core": { + "handlers": ["console"], + "level": values.Value( + "INFO", + environ_name="LOGGING_LEVEL_LOGGERS_APP", + environ_prefix=None, + ), + "propagate": True, + }, + }, + } + + API_USERS_LIST_LIMIT = values.PositiveIntegerValue( + default=5, + environ_name="API_USERS_LIST_LIMIT", + environ_prefix=None, + ) + + # Storage compute + + # pylint: disable=invalid-name + @property + def ENVIRONMENT(self): + """Environment in which the application is launched.""" + return self.__class__.__name__.lower() + + # pylint: disable=invalid-name + @property + def RELEASE(self): + """ + Return the release information. + + Delegate to the module function to enable easier testing. + """ + return get_release() + + # pylint: disable=invalid-name + @property + def PARLER_LANGUAGES(self): + """ + Return languages for Parler computed from the LANGUAGES and LANGUAGE_CODE settings. + """ + return { + self.SITE_ID: tuple({"code": code} for code, _name in self.LANGUAGES), + "default": { + "fallbacks": [self.LANGUAGE_CODE], + "hide_untranslated": False, + }, + } + + @classmethod + def post_setup(cls): + """Post setup configuration. + This is the place where you can configure settings that require other + settings to be loaded. + """ + super().post_setup() + + # The SENTRY_DSN setting should be available to activate sentry for an environment + if cls.SENTRY_DSN is not None: + sentry_sdk.init( + dsn=cls.SENTRY_DSN, + environment=cls.__name__.lower(), + release=get_release(), + integrations=[DjangoIntegration()], + ) + sentry_sdk.set_tag("application", "backend") + + if ( + cls.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION + and cls.OIDC_ALLOW_DUPLICATE_EMAILS + ): + raise ValueError( + "Both OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION and " + "OIDC_ALLOW_DUPLICATE_EMAILS cannot be set to True simultaneously. " + ) + + +class Build(Base): + """Settings used when the application is built. + + This environment should not be used to run the application. Just to build it with non-blocking + settings. + """ + + SESSION_CACHE_ALIAS = "default" + CACHES = { + "default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}, + } + SECRET_KEY = values.Value("DummyKey") + STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": values.Value( + "whitenoise.storage.CompressedManifestStaticFilesStorage", + environ_name="STORAGES_STATICFILES_BACKEND", + ), + }, + } + + +class Development(Base): + """ + Development environment settings + + We set DEBUG to True and configure the server to respond from all hosts. + """ + + ALLOWED_HOSTS = ["*"] + CORS_ALLOW_ALL_ORIGINS = True + CSRF_TRUSTED_ORIGINS = [ + "http://localhost:8920", + ] + DEBUG = True + LOAD_E2E_URLS = True + + SESSION_COOKIE_NAME = "calendar_sessionid" + + USE_SWAGGER = True + + DEBUG_TOOLBAR_CONFIG = { + "SHOW_TOOLBAR_CALLBACK": lambda request: True, + } + + def __init__(self): + # pylint: disable=invalid-name + self.MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] + # pylint: disable=invalid-name + self.INSTALLED_APPS += [ + "django_extensions", + "drf_spectacular_sidecar", + "debug_toolbar", + "e2e", + ] + + +class Test(Base): + """Test environment settings""" + + SESSION_CACHE_ALIAS = "default" + CACHES = { + "default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}, + } + + PASSWORD_HASHERS = [ + "django.contrib.auth.hashers.MD5PasswordHasher", + ] + USE_SWAGGER = True + + CELERY_TASK_ALWAYS_EAGER = values.BooleanValue(True) + + OIDC_STORE_ACCESS_TOKEN = False + OIDC_STORE_REFRESH_TOKEN = False + + def __init__(self): + # pylint: disable=invalid-name + self.INSTALLED_APPS += ["drf_spectacular_sidecar", "e2e"] + + +class ContinuousIntegration(Test): + """ + Continuous Integration environment settings + + nota bene: it should inherit from the Test environment. + """ + + +class Production(Base): + """ + Production environment settings + + You must define the ALLOWED_HOSTS environment variable in Production + configuration (and derived configurations): + ALLOWED_HOSTS=["foo.com", "foo.fr"] + """ + + # Security + # Add allowed host from environment variables. + # The machine hostname is added by default, + # it makes the application pingable by a load balancer on the same machine by example + ALLOWED_HOSTS = [ + *values.ListValue([], environ_name="ALLOWED_HOSTS"), + gethostbyname(gethostname()), + ] + CSRF_TRUSTED_ORIGINS = values.ListValue([]) + SECURE_BROWSER_XSS_FILTER = True + SECURE_CONTENT_TYPE_NOSNIFF = True + + # SECURE_PROXY_SSL_HEADER allows to fix the scheme in Django's HttpRequest + # object when your application is behind a reverse proxy. + # + # Keep this SECURE_PROXY_SSL_HEADER configuration only if : + # - your Django app is behind a proxy. + # - your proxy strips the X-Forwarded-Proto header from all incoming requests + # - Your proxy sets the X-Forwarded-Proto header and sends it to Django + # + # In other cases, you should comment the following line to avoid security issues. + # SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") + SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") + SECURE_HSTS_SECONDS = 60 + SECURE_HSTS_PRELOAD = True + SECURE_HSTS_INCLUDE_SUBDOMAINS = True + SECURE_SSL_REDIRECT = True + SECURE_REDIRECT_EXEMPT = [ + "^__lbheartbeat__", + "^__heartbeat__", + ] + + # Modern browsers require to have the `secure` attribute on cookies with `Samesite=none` + CSRF_COOKIE_SECURE = True + SESSION_COOKIE_SECURE = True + + # Privacy + SECURE_REFERRER_POLICY = "same-origin" + + +class Feature(Production): + """ + Feature environment settings + + nota bene: it should inherit from the Production environment. + """ + + +class Staging(Production): + """ + Staging environment settings + + nota bene: it should inherit from the Production environment. + """ + + +class PreProduction(Production): + """ + Pre-production environment settings + + nota bene: it should inherit from the Production environment. + """ diff --git a/src/backend/calendars/urls.py b/src/backend/calendars/urls.py new file mode 100644 index 0000000..8c32c8d --- /dev/null +++ b/src/backend/calendars/urls.py @@ -0,0 +1,58 @@ +"""URL configuration for the calendars project""" + +from django.conf import settings +from django.conf.urls.static import static +from django.contrib import admin +from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import include, path, re_path + +from drf_spectacular.views import ( + SpectacularJSONAPIView, + SpectacularRedocView, + SpectacularSwaggerView, +) + +from core.api.viewsets_caldav import CalDAVDiscoveryView + +urlpatterns = [ + path("admin/", admin.site.urls), + # CalDAV discovery - must be at root level per RFC 6764 + path(".well-known/caldav", CalDAVDiscoveryView.as_view(), name="caldav-discovery"), + path("", include("core.urls")), +] + +if settings.DEBUG: + from debug_toolbar.toolbar import debug_toolbar_urls + + urlpatterns = ( + urlpatterns + + staticfiles_urlpatterns() + + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + + debug_toolbar_urls() + ) + +if settings.LOAD_E2E_URLS: + urlpatterns += [path("", include("e2e.urls"))] + + +if settings.USE_SWAGGER or settings.DEBUG: + urlpatterns += [ + path( + f"api/{settings.API_VERSION}/swagger.json", + SpectacularJSONAPIView.as_view( + api_version=settings.API_VERSION, + urlconf="core.urls", + ), + name="client-api-schema", + ), + path( + f"api/{settings.API_VERSION}/swagger/", + SpectacularSwaggerView.as_view(url_name="client-api-schema"), + name="swagger-ui-schema", + ), + re_path( + f"api/{settings.API_VERSION}/redoc/", + SpectacularRedocView.as_view(url_name="client-api-schema"), + name="redoc-schema", + ), + ] diff --git a/src/backend/calendars/wsgi.py b/src/backend/calendars/wsgi.py new file mode 100644 index 0000000..69344b5 --- /dev/null +++ b/src/backend/calendars/wsgi.py @@ -0,0 +1,17 @@ +""" +WSGI config for the calendars project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from configurations.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "calendars.settings") +os.environ.setdefault("DJANGO_CONFIGURATION", "Development") + +application = get_wsgi_application() diff --git a/src/backend/core/__init__.py b/src/backend/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/admin.py b/src/backend/core/admin.py new file mode 100644 index 0000000..1efc8ae --- /dev/null +++ b/src/backend/core/admin.py @@ -0,0 +1,93 @@ +"""Admin classes and registrations for core app.""" + +from django.contrib import admin +from django.contrib.auth import admin as auth_admin +from django.utils.translation import gettext_lazy as _ + +from . import models + + +@admin.register(models.User) +class UserAdmin(auth_admin.UserAdmin): + """Admin class for the User model""" + + fieldsets = ( + ( + None, + { + "fields": ( + "id", + "admin_email", + "password", + ) + }, + ), + ( + _("Personal info"), + { + "fields": ( + "sub", + "email", + "full_name", + "short_name", + "language", + "timezone", + ) + }, + ), + ( + _("Permissions"), + { + "fields": ( + "is_active", + "is_device", + "is_staff", + "is_superuser", + "groups", + "user_permissions", + ), + }, + ), + (_("Important dates"), {"fields": ("created_at", "updated_at")}), + ) + add_fieldsets = ( + ( + None, + { + "classes": ("wide",), + "fields": ("email", "password1", "password2"), + }, + ), + ) + list_display = ( + "id", + "sub", + "full_name", + "admin_email", + "email", + "is_active", + "is_staff", + "is_superuser", + "is_device", + "created_at", + "updated_at", + ) + list_filter = ("is_staff", "is_superuser", "is_device", "is_active") + ordering = ( + "is_active", + "-is_superuser", + "-is_staff", + "-is_device", + "-updated_at", + "full_name", + ) + readonly_fields = ( + "id", + "sub", + "email", + "full_name", + "short_name", + "created_at", + "updated_at", + ) + search_fields = ("id", "sub", "admin_email", "email", "full_name") diff --git a/src/backend/core/api/__init__.py b/src/backend/core/api/__init__.py new file mode 100644 index 0000000..6fcdb8b --- /dev/null +++ b/src/backend/core/api/__init__.py @@ -0,0 +1,34 @@ +"""Calendars core API endpoints""" + +from django.conf import settings +from django.core.exceptions import ValidationError as DjangoValidationError + +from drf_standardized_errors.handler import exception_handler as drf_exception_handler +from rest_framework import exceptions as drf_exceptions +from rest_framework.decorators import api_view +from rest_framework.response import Response +from rest_framework.serializers import as_serializer_error + + +def exception_handler(exc, context): + """Handle Django ValidationError as an accepted exception. + + For the parameters, see ``exception_handler`` + This code comes from twidi's gist: + https://gist.github.com/twidi/9d55486c36b6a51bdcb05ce3a763e79f + """ + if isinstance(exc, DjangoValidationError): + exc = drf_exceptions.ValidationError(as_serializer_error(exc)) + + return drf_exception_handler(exc, context) + + +# pylint: disable=unused-argument +@api_view(["GET"]) +def get_frontend_configuration(request): + """Returns the frontend configuration dict as configured in settings.""" + frontend_configuration = { + "LANGUAGE_CODE": settings.LANGUAGE_CODE, + } + frontend_configuration.update(settings.FRONTEND_CONFIGURATION) + return Response(frontend_configuration) diff --git a/src/backend/core/api/fields.py b/src/backend/core/api/fields.py new file mode 100644 index 0000000..1125622 --- /dev/null +++ b/src/backend/core/api/fields.py @@ -0,0 +1,25 @@ +"""A JSONField for DRF to handle serialization/deserialization.""" + +import json + +from rest_framework import serializers + + +class JSONField(serializers.Field): + """ + A custom field for handling JSON data. + """ + + def to_representation(self, value): + """ + Convert the JSON string to a Python dictionary for serialization. + """ + return value + + def to_internal_value(self, data): + """ + Convert the Python dictionary to a JSON string for deserialization. + """ + if data is None: + return None + return json.dumps(data) diff --git a/src/backend/core/api/permissions.py b/src/backend/core/api/permissions.py new file mode 100644 index 0000000..f94a19d --- /dev/null +++ b/src/backend/core/api/permissions.py @@ -0,0 +1,79 @@ +"""Permission handlers for the calendars core app.""" + +from django.core import exceptions + +from rest_framework import permissions + +ACTION_FOR_METHOD_TO_PERMISSION = { + "versions_detail": {"DELETE": "versions_destroy", "GET": "versions_retrieve"}, + "children": {"GET": "children_list", "POST": "children_create"}, +} + + +class IsAuthenticated(permissions.BasePermission): + """ + Allows access only to authenticated users. Alternative method checking the presence + of the auth token to avoid hitting the database. + """ + + def has_permission(self, request, view): + return bool(request.auth) or request.user.is_authenticated + + +class IsAuthenticatedOrSafe(IsAuthenticated): + """Allows access to authenticated users (or anonymous users but only on safe methods).""" + + def has_permission(self, request, view): + if request.method in permissions.SAFE_METHODS: + return True + return super().has_permission(request, view) + + +class IsSelf(IsAuthenticated): + """ + Allows access only to authenticated users. Alternative method checking the presence + of the auth token to avoid hitting the database. + """ + + def has_object_permission(self, request, view, obj): + """Write permissions are only allowed to the user itself.""" + return obj == request.user + + +class IsOwnedOrPublic(IsAuthenticated): + """ + Allows access to authenticated users only for objects that are owned or not related + to any user via the "owner" field. + """ + + def has_object_permission(self, request, view, obj): + """Unsafe permissions are only allowed for the owner of the object.""" + if obj.owner == request.user: + return True + + if request.method in permissions.SAFE_METHODS and obj.owner is None: + return True + + try: + return obj.user == request.user + except exceptions.ObjectDoesNotExist: + return False + + +class AccessPermission(permissions.BasePermission): + """Permission class for access objects.""" + + def has_permission(self, request, view): + return request.user.is_authenticated or view.action not in [ + "create", + ] + + def has_object_permission(self, request, view, obj): + """Check permission for a given object.""" + abilities = obj.get_abilities(request.user) + action = view.action + try: + action = ACTION_FOR_METHOD_TO_PERMISSION[view.action][request.method] + except KeyError: + pass + return abilities.get(action, False) diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py new file mode 100644 index 0000000..4752ca1 --- /dev/null +++ b/src/backend/core/api/serializers.py @@ -0,0 +1,155 @@ +"""Client serializers for the calendars core app.""" + +import json +from datetime import timedelta + +from django.conf import settings +from django.db.models import Q +from django.utils.translation import gettext_lazy as _ + +from rest_framework import exceptions, serializers + +from core import models + + +class UserLiteSerializer(serializers.ModelSerializer): + """Serialize users with limited fields.""" + + class Meta: + model = models.User + fields = ["id", "full_name", "short_name"] + read_only_fields = ["id", "full_name", "short_name"] + + +class BaseAccessSerializer(serializers.ModelSerializer): + """Serialize template accesses.""" + + abilities = serializers.SerializerMethodField(read_only=True) + + def update(self, instance, validated_data): + """Make "user" field is readonly but only on update.""" + validated_data.pop("user", None) + return super().update(instance, validated_data) + + def get_abilities(self, access) -> dict: + """Return abilities of the logged-in user on the instance.""" + request = self.context.get("request") + if request: + return access.get_abilities(request.user) + return {} + + def validate(self, attrs): + """ + Check access rights specific to writing (create/update) + """ + request = self.context.get("request") + user = getattr(request, "user", None) + role = attrs.get("role") + + # Update + if self.instance: + can_set_role_to = self.instance.get_abilities(user)["set_role_to"] + + if role and role not in can_set_role_to: + message = ( + f"You are only allowed to set role to {', '.join(can_set_role_to)}" + if can_set_role_to + else "You are not allowed to set this role for this template." + ) + raise exceptions.PermissionDenied(message) + + # Create + else: + try: + resource_id = self.context["resource_id"] + except KeyError as exc: + raise exceptions.ValidationError( + "You must set a resource ID in kwargs to create a new access." + ) from exc + + if not self.Meta.model.objects.filter( # pylint: disable=no-member + Q(user=user) | Q(team__in=user.teams), + role__in=[models.RoleChoices.OWNER, models.RoleChoices.ADMIN], + **{self.Meta.resource_field_name: resource_id}, # pylint: disable=no-member + ).exists(): + raise exceptions.PermissionDenied( + "You are not allowed to manage accesses for this resource." + ) + + if ( + role == models.RoleChoices.OWNER + and not self.Meta.model.objects.filter( # pylint: disable=no-member + Q(user=user) | Q(team__in=user.teams), + role=models.RoleChoices.OWNER, + **{self.Meta.resource_field_name: resource_id}, # pylint: disable=no-member + ).exists() + ): + raise exceptions.PermissionDenied( + "Only owners of a resource can assign other users as owners." + ) + + # pylint: disable=no-member + attrs[f"{self.Meta.resource_field_name}_id"] = self.context["resource_id"] + return attrs + + +class UserSerializer(serializers.ModelSerializer): + """Serialize users.""" + + class Meta: + model = models.User + fields = [ + "id", + "email", + "full_name", + "short_name", + "language", + ] + read_only_fields = ["id", "email", "full_name", "short_name"] + + +class UserMeSerializer(UserSerializer): + """Serialize users for me endpoint.""" + + class Meta: + model = models.User + fields = UserSerializer.Meta.fields + read_only_fields = UserSerializer.Meta.read_only_fields + + +# CalDAV serializers +class CalendarSerializer(serializers.ModelSerializer): + """Serializer for Calendar model.""" + + class Meta: + model = models.Calendar + fields = [ + "id", + "name", + "color", + "description", + "is_default", + "is_visible", + "created_at", + "updated_at", + ] + read_only_fields = ["id", "is_default", "created_at", "updated_at"] + + +class CalendarCreateSerializer(serializers.ModelSerializer): + """Serializer for creating a Calendar.""" + + class Meta: + model = models.Calendar + fields = ["name", "color", "description"] + + +class CalendarShareSerializer(serializers.ModelSerializer): + """Serializer for CalendarShare model.""" + + shared_with_email = serializers.EmailField(write_only=True) + + class Meta: + model = models.CalendarShare + fields = ["id", "shared_with_email", "permission", "is_visible", "created_at"] + read_only_fields = ["id", "created_at"] diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py new file mode 100644 index 0000000..5cef50c --- /dev/null +++ b/src/backend/core/api/viewsets.py @@ -0,0 +1,397 @@ +"""API endpoints""" +# pylint: disable=too-many-lines + +import json +import logging +import re +from urllib.parse import unquote, urlparse + +from django.conf import settings +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.db import models as db +from django.db import transaction +from django.urls import reverse +from django.utils.decorators import method_decorator +from django.utils.text import slugify + +import rest_framework as drf +from corsheaders.middleware import ( + ACCESS_CONTROL_ALLOW_METHODS, + ACCESS_CONTROL_ALLOW_ORIGIN, +) +from lasuite.oidc_login.decorators import refresh_oidc_access_token +from rest_framework import filters, mixins, status, viewsets +from rest_framework import response as drf_response +from rest_framework.decorators import action +from rest_framework.permissions import AllowAny, IsAuthenticated +from rest_framework.throttling import UserRateThrottle +from rest_framework_api_key.permissions import HasAPIKey + +from core import enums, models +from core.services.caldav_service import CalendarService + +from . import permissions, serializers + +logger = logging.getLogger(__name__) + + +# pylint: disable=too-many-ancestors + + +class NestedGenericViewSet(viewsets.GenericViewSet): + """ + A generic Viewset aims to be used in a nested route context. + e.g: `/api/v1.0/resource_1//resource_2//` + + It allows to define all url kwargs and lookup fields to perform the lookup. + """ + + lookup_fields: list[str] = ["pk"] + lookup_url_kwargs: list[str] = [] + + def __getattribute__(self, item): + """ + This method is overridden to allow to get the last lookup field or lookup url kwarg + when accessing the `lookup_field` or `lookup_url_kwarg` attribute. This is useful + to keep compatibility with all methods used by the parent class `GenericViewSet`. + """ + if item in ["lookup_field", "lookup_url_kwarg"]: + return getattr(self, item + "s", [None])[-1] + + return super().__getattribute__(item) + + def get_queryset(self): + """ + Get the list of items for this view. + + `lookup_fields` attribute is enumerated here to perform the nested lookup. + """ + queryset = super().get_queryset() + + # The last lookup field is removed to perform the nested lookup as it corresponds + # to the object pk, it is used within get_object method. + lookup_url_kwargs = ( + self.lookup_url_kwargs[:-1] + if self.lookup_url_kwargs + else self.lookup_fields[:-1] + ) + + filter_kwargs = {} + for index, lookup_url_kwarg in enumerate(lookup_url_kwargs): + if lookup_url_kwarg not in self.kwargs: + raise KeyError( + f"Expected view {self.__class__.__name__} to be called with a URL " + f'keyword argument named "{lookup_url_kwarg}". Fix your URL conf, or ' + "set the `.lookup_fields` attribute on the view correctly." + ) + + filter_kwargs.update( + {self.lookup_fields[index]: self.kwargs[lookup_url_kwarg]} + ) + + return queryset.filter(**filter_kwargs) + + +class SerializerPerActionMixin: + """ + A mixin to allow to define serializer classes for each action. + + This mixin is useful to avoid to define a serializer class for each action in the + `get_serializer_class` method. + + Example: + ``` + class MyViewSet(SerializerPerActionMixin, viewsets.GenericViewSet): + serializer_class = MySerializer + list_serializer_class = MyListSerializer + retrieve_serializer_class = MyRetrieveSerializer + ``` + """ + + def get_serializer_class(self): + """ + Return the serializer class to use depending on the action. + """ + if serializer_class := getattr(self, f"{self.action}_serializer_class", None): + return serializer_class + return super().get_serializer_class() + + +class Pagination(drf.pagination.PageNumberPagination): + """Pagination to display no more than 100 objects per page sorted by creation date.""" + + ordering = "-created_on" + max_page_size = settings.MAX_PAGE_SIZE + page_size_query_param = "page_size" + + +class UserListThrottleBurst(UserRateThrottle): + """Throttle for the user list endpoint.""" + + scope = "user_list_burst" + + +class UserListThrottleSustained(UserRateThrottle): + """Throttle for the user list endpoint.""" + + scope = "user_list_sustained" + + +class UserViewSet( + SerializerPerActionMixin, + drf.mixins.UpdateModelMixin, + viewsets.GenericViewSet, + drf.mixins.ListModelMixin, +): + """User ViewSet""" + + permission_classes = [permissions.IsSelf] + queryset = models.User.objects.all().filter(is_active=True) + serializer_class = serializers.UserSerializer + get_me_serializer_class = serializers.UserMeSerializer + pagination_class = None + throttle_classes = [] + + def get_throttles(self): + self.throttle_classes = [] + if self.action == "list": + self.throttle_classes = [UserListThrottleBurst, UserListThrottleSustained] + + return super().get_throttles() + + def get_queryset(self): + """ + Limit listed users by querying the email field. + If query contains "@", search exactly. Otherwise return empty. + """ + queryset = self.queryset + + if self.action != "list": + return queryset + + if not (query := self.request.query_params.get("q", "")) or len(query) < 5: + return queryset.none() + + # For emails, match exactly + if "@" in query: + return queryset.filter(email__iexact=query).order_by("email")[ + : settings.API_USERS_LIST_LIMIT + ] + + # For non-email queries, return empty (no fuzzy search) + return queryset.none() + + @drf.decorators.action( + detail=False, + methods=["get"], + url_name="me", + url_path="me", + ) + def get_me(self, request): + """ + Return information on currently logged user + """ + context = {"request": request} + return drf.response.Response( + self.get_serializer(request.user, context=context).data + ) + + +class ConfigView(drf.views.APIView): + """API ViewSet for sharing some public settings.""" + + permission_classes = [AllowAny] + + def get(self, request): + """ + GET /api/v1.0/config/ + Return a dictionary of public settings. + """ + array_settings = [ + "ENVIRONMENT", + "FRONTEND_THEME", + "FRONTEND_MORE_LINK", + "FRONTEND_FEEDBACK_BUTTON_SHOW", + "FRONTEND_FEEDBACK_BUTTON_IDLE", + "FRONTEND_FEEDBACK_ITEMS", + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_ENABLED", + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL", + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL", + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH", + "FRONTEND_HIDE_GAUFRE", + "MEDIA_BASE_URL", + "LANGUAGES", + "LANGUAGE_CODE", + "SENTRY_DSN", + ] + dict_settings = {} + for setting in array_settings: + if hasattr(settings, setting): + dict_settings[setting] = getattr(settings, setting) + + dict_settings["theme_customization"] = self._load_theme_customization() + + return drf.response.Response(dict_settings) + + def _load_theme_customization(self): + if not settings.THEME_CUSTOMIZATION_FILE_PATH: + return {} + + cache_key = ( + f"theme_customization_{slugify(settings.THEME_CUSTOMIZATION_FILE_PATH)}" + ) + theme_customization = cache.get(cache_key, {}) + if theme_customization: + return theme_customization + + try: + with open( + settings.THEME_CUSTOMIZATION_FILE_PATH, "r", encoding="utf-8" + ) as f: + theme_customization = json.load(f) + except FileNotFoundError: + logger.error( + "Configuration file not found: %s", + settings.THEME_CUSTOMIZATION_FILE_PATH, + ) + except json.JSONDecodeError: + logger.error( + "Configuration file is not a valid JSON: %s", + settings.THEME_CUSTOMIZATION_FILE_PATH, + ) + else: + cache.set( + cache_key, + theme_customization, + settings.THEME_CUSTOMIZATION_CACHE_TIMEOUT, + ) + + return theme_customization + + +# CalDAV ViewSets +class CalendarViewSet( + mixins.ListModelMixin, + mixins.RetrieveModelMixin, + mixins.CreateModelMixin, + mixins.UpdateModelMixin, + mixins.DestroyModelMixin, + viewsets.GenericViewSet, +): + """ + ViewSet for managing user calendars. + + list: Get all calendars accessible by the user (owned + shared) + retrieve: Get a specific calendar + create: Create a new calendar + update: Update calendar properties + destroy: Delete a calendar + """ + + permission_classes = [IsAuthenticated] + serializer_class = serializers.CalendarSerializer + + def get_queryset(self): + """Return calendars owned by or shared with the current user.""" + user = self.request.user + owned = models.Calendar.objects.filter(owner=user) + shared_ids = models.CalendarShare.objects.filter(shared_with=user).values_list( + "calendar_id", flat=True + ) + shared = models.Calendar.objects.filter(id__in=shared_ids) + return owned.union(shared).order_by("-is_default", "name") + + def get_serializer_class(self): + if self.action == "create": + return serializers.CalendarCreateSerializer + return serializers.CalendarSerializer + + def perform_create(self, serializer): + """Create a new calendar via CalendarService.""" + service = CalendarService() + calendar = service.create_calendar( + user=self.request.user, + name=serializer.validated_data["name"], + color=serializer.validated_data.get("color", "#3174ad"), + ) + # Update the serializer instance with the created calendar + serializer.instance = calendar + + def perform_destroy(self, instance): + """Delete calendar. Prevent deletion of default calendar.""" + if instance.is_default: + raise ValueError("Cannot delete the default calendar.") + if instance.owner != self.request.user: + raise PermissionError("You can only delete your own calendars.") + instance.delete() + + @action(detail=True, methods=["patch"]) + def toggle_visibility(self, request, pk=None): + """Toggle calendar visibility.""" + calendar = self.get_object() + + # Check if it's a shared calendar + share = models.CalendarShare.objects.filter( + calendar=calendar, shared_with=request.user + ).first() + + if share: + share.is_visible = not share.is_visible + share.save() + is_visible = share.is_visible + elif calendar.owner == request.user: + calendar.is_visible = not calendar.is_visible + calendar.save() + is_visible = calendar.is_visible + else: + return drf_response.Response( + {"error": "Permission denied"}, status=status.HTTP_403_FORBIDDEN + ) + + return drf_response.Response({"is_visible": is_visible}) + + @action( + detail=True, + methods=["post"], + serializer_class=serializers.CalendarShareSerializer, + ) + def share(self, request, pk=None): + """Share calendar with another user.""" + calendar = self.get_object() + + if calendar.owner != request.user: + return drf_response.Response( + {"error": "Only the owner can share this calendar"}, + status=status.HTTP_403_FORBIDDEN, + ) + + serializer = serializers.CalendarShareSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + email = serializer.validated_data["shared_with_email"] + try: + user_to_share = models.User.objects.get(email=email) + except models.User.DoesNotExist: + return drf_response.Response( + {"error": "User not found"}, status=status.HTTP_404_NOT_FOUND + ) + + share, created = models.CalendarShare.objects.get_or_create( + calendar=calendar, + shared_with=user_to_share, + defaults={ + "permission": serializer.validated_data.get("permission", "read") + }, + ) + + if not created: + share.permission = serializer.validated_data.get( + "permission", share.permission + ) + share.save() + + return drf_response.Response( + serializers.CalendarShareSerializer(share).data, + status=status.HTTP_201_CREATED if created else status.HTTP_200_OK, + ) diff --git a/src/backend/core/api/viewsets_caldav.py b/src/backend/core/api/viewsets_caldav.py new file mode 100644 index 0000000..710b4df --- /dev/null +++ b/src/backend/core/api/viewsets_caldav.py @@ -0,0 +1,220 @@ +"""CalDAV proxy views for forwarding requests to DAViCal.""" + +import logging + +from django.conf import settings +from django.http import HttpResponse +from django.utils.decorators import method_decorator +from django.views import View +from django.views.decorators.csrf import csrf_exempt + +import requests + +from core.services.caldav_service import DAViCalClient + +logger = logging.getLogger(__name__) + + +@method_decorator(csrf_exempt, name="dispatch") +class CalDAVProxyView(View): + """ + Proxy view that forwards all CalDAV requests to DAViCal. + Handles authentication and adds appropriate headers. + + CSRF protection is disabled because CalDAV uses non-standard HTTP methods + (PROPFIND, REPORT, etc.) that don't work with Django's CSRF middleware. + Authentication is handled via session cookies instead. + """ + + def dispatch(self, request, *args, **kwargs): + """Forward all HTTP methods to DAViCal.""" + # Handle CORS preflight requests + if request.method == "OPTIONS": + response = HttpResponse(status=200) + response["Access-Control-Allow-Methods"] = ( + "GET, OPTIONS, PROPFIND, REPORT, MKCOL, MKCALENDAR, PUT, DELETE" + ) + response["Access-Control-Allow-Headers"] = ( + "Content-Type, depth, authorization, if-match, if-none-match, prefer" + ) + return response + + if not request.user.is_authenticated: + return HttpResponse(status=401) + + # Ensure user exists in DAViCal before making requests + try: + davical_client = DAViCalClient() + davical_client.ensure_user_exists(request.user) + except Exception as e: + logger.warning("Failed to ensure user exists in DAViCal: %s", str(e)) + # Continue anyway - user might already exist + + # Build the DAViCal URL + davical_url = getattr(settings, "DAVICAL_URL", "http://davical:80") + path = kwargs.get("path", "") + + # Use user email as the principal (DAViCal uses email as username) + user_principal = request.user.email + + # Handle root CalDAV requests - return principal collection + if not path or path == user_principal: + # For PROPFIND on root, return the user's principal collection + if request.method == "PROPFIND": + # Get the request path to match the href in response + request_path = request.path + if not request_path.endswith("/"): + request_path += "/" + + # Return multistatus with href matching request URL and calendar-home-set + multistatus = f""" + + + {request_path} + + + {user_principal} + + /api/v1.0/caldav/{user_principal}/ + + + HTTP/1.1 200 OK + + +""" + response = HttpResponse( + content=multistatus, + status=207, + content_type="application/xml; charset=utf-8", + ) + return response + + # For other methods, redirect to principal URL + target_url = f"{davical_url}/caldav.php/{user_principal}/" + else: + # Build target URL with path + # Remove leading slash if present + clean_path = path.lstrip("/") + if clean_path.startswith(user_principal): + # Path already includes principal + target_url = f"{davical_url}/caldav.php/{clean_path}" + else: + # Path is relative to principal + target_url = f"{davical_url}/caldav.php/{user_principal}/{clean_path}" + + # Prepare headers for DAViCal + # Set headers to tell DAViCal it's behind a proxy so it generates correct URLs + script_name = "/api/v1.0/caldav" + headers = { + "Content-Type": request.content_type or "application/xml", + "X-Forwarded-User": user_principal, + "X-Forwarded-For": request.META.get("REMOTE_ADDR", ""), + "X-Forwarded-Prefix": script_name, + "X-Forwarded-Host": request.get_host(), + "X-Forwarded-Proto": request.scheme, + "X-Script-Name": script_name, # Tell DAViCal the base path + } + + # DAViCal authentication: users with password '*' use external auth + # We send the username via X-Forwarded-User header + # For HTTP Basic Auth, we use the email as username with empty password + # This works with DAViCal's external authentication when trust_x_forwarded is true + auth = (user_principal, "") + + # Copy relevant headers from the original request + if "HTTP_DEPTH" in request.META: + headers["Depth"] = request.META["HTTP_DEPTH"] + if "HTTP_IF_MATCH" in request.META: + headers["If-Match"] = request.META["HTTP_IF_MATCH"] + if "HTTP_IF_NONE_MATCH" in request.META: + headers["If-None-Match"] = request.META["HTTP_IF_NONE_MATCH"] + if "HTTP_PREFER" in request.META: + headers["Prefer"] = request.META["HTTP_PREFER"] + + # Get request body + body = request.body if request.body else None + + try: + # Forward the request to DAViCal + # Use HTTP Basic Auth with username (email) and empty password + # DAViCal will authenticate based on X-Forwarded-User header when trust_x_forwarded is true + logger.debug( + "Forwarding %s request to DAViCal: %s (user: %s)", + request.method, + target_url, + user_principal, + ) + response = requests.request( + method=request.method, + url=target_url, + headers=headers, + data=body, + auth=auth, + timeout=30, + allow_redirects=False, + ) + + # Log authentication failures for debugging + if response.status_code == 401: + logger.warning( + "DAViCal returned 401 for user %s at %s. Headers sent: %s", + user_principal, + target_url, + headers, + ) + + # Build Django response + django_response = HttpResponse( + content=response.content, + status=response.status_code, + content_type=response.headers.get("Content-Type", "application/xml"), + ) + + # Copy relevant headers from DAViCal response + for header in ["ETag", "DAV", "Allow", "Location"]: + if header in response.headers: + django_response[header] = response.headers[header] + + return django_response + + except requests.exceptions.RequestException as e: + logger.error("DAViCal proxy error: %s", str(e)) + return HttpResponse( + content=f"CalDAV server error: {str(e)}", + status=502, + content_type="text/plain", + ) + + +@method_decorator(csrf_exempt, name="dispatch") +class CalDAVDiscoveryView(View): + """ + Handle CalDAV discovery requests (well-known URLs). + + Per RFC 6764, this endpoint should redirect to the CalDAV server base URL, + not to a user-specific principal. Clients will then perform PROPFIND on + the base URL to discover their principal. + + CSRF protection is disabled because CalDAV uses non-standard HTTP methods + and this endpoint should be accessible without authentication. + """ + + def dispatch(self, request, *args, **kwargs): + """Handle discovery requests.""" + # Handle CORS preflight requests + if request.method == "OPTIONS": + response = HttpResponse(status=200) + response["Access-Control-Allow-Methods"] = "GET, OPTIONS, PROPFIND" + response["Access-Control-Allow-Headers"] = ( + "Content-Type, depth, authorization" + ) + return response + + # Note: Authentication is not required for discovery per RFC 6764 + # Clients need to discover the CalDAV URL before authenticating + + # Return redirect to CalDAV server base URL + caldav_base_url = f"/api/v1.0/caldav/" + response = HttpResponse(status=301) + response["Location"] = caldav_base_url + return response diff --git a/src/backend/core/apps.py b/src/backend/core/apps.py new file mode 100644 index 0000000..121bcb2 --- /dev/null +++ b/src/backend/core/apps.py @@ -0,0 +1,19 @@ +"""Calendars Core application""" + +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class CoreConfig(AppConfig): + """Configuration class for the calendars core app.""" + + name = "core" + app_label = "core" + verbose_name = _("calendars core application") + + def ready(self): + """ + Import signals when the app is ready. + """ + # pylint: disable=import-outside-toplevel, unused-import + from . import signals # noqa: PLC0415 diff --git a/src/backend/core/authentication/__init__.py b/src/backend/core/authentication/__init__.py new file mode 100644 index 0000000..bcd07f1 --- /dev/null +++ b/src/backend/core/authentication/__init__.py @@ -0,0 +1,52 @@ +"""Custom authentication classes for the calendars core app""" + +from django.conf import settings + +from rest_framework.authentication import BaseAuthentication +from rest_framework.exceptions import AuthenticationFailed + + +class ServerToServerAuthentication(BaseAuthentication): + """ + Custom authentication class for server-to-server requests. + Validates the presence and correctness of the Authorization header. + """ + + AUTH_HEADER = "Authorization" + TOKEN_TYPE = "Bearer" # noqa S105 + + def authenticate(self, request): + """ + Authenticate the server-to-server request by validating the Authorization header. + + This method checks if the Authorization header is present in the request, ensures it + contains a valid token with the correct format, and verifies the token against the + list of allowed server-to-server tokens. If the header is missing, improperly formatted, + or contains an invalid token, an AuthenticationFailed exception is raised. + + Returns: + None: If authentication is successful + (no user is authenticated for server-to-server requests). + + Raises: + AuthenticationFailed: If the Authorization header is missing, malformed, + or contains an invalid token. + """ + auth_header = request.headers.get(self.AUTH_HEADER) + if not auth_header: + raise AuthenticationFailed("Authorization header is missing.") + + # Validate token format and existence + auth_parts = auth_header.split(" ") + if len(auth_parts) != 2 or auth_parts[0] != self.TOKEN_TYPE: + raise AuthenticationFailed("Invalid authorization header.") + + token = auth_parts[1] + if token not in settings.SERVER_TO_SERVER_API_TOKENS: + raise AuthenticationFailed("Invalid server-to-server token.") + + # Authentication is successful, but no user is authenticated + + def authenticate_header(self, request): + """Return the WWW-Authenticate header value.""" + return f"{self.TOKEN_TYPE} realm='Create item server to server'" diff --git a/src/backend/core/authentication/backends.py b/src/backend/core/authentication/backends.py new file mode 100644 index 0000000..5c38894 --- /dev/null +++ b/src/backend/core/authentication/backends.py @@ -0,0 +1,54 @@ +"""Authentication Backends for the Calendars core app.""" + +import logging + +from django.conf import settings +from django.core.exceptions import SuspiciousOperation +from django.utils.translation import gettext_lazy as _ + +from lasuite.oidc_login.backends import ( + OIDCAuthenticationBackend as LaSuiteOIDCAuthenticationBackend, +) + +from core.authentication.exceptions import UserCannotAccessApp +from core.models import DuplicateEmailError + +logger = logging.getLogger(__name__) + + +class OIDCAuthenticationBackend(LaSuiteOIDCAuthenticationBackend): + """Custom OpenID Connect (OIDC) Authentication Backend. + + This class overrides the default OIDC Authentication Backend to accommodate differences + in the User and Identity models, and handles signed and/or encrypted UserInfo response. + """ + + def get_extra_claims(self, user_info): + """ + Return extra claims from user_info. + + Args: + user_info (dict): The user information dictionary. + + Returns: + dict: A dictionary of extra claims. + """ + + # We need to add the claims that we want to store so that they are + # available in the post_get_or_create_user method. + claims_to_store = { + claim: user_info.get(claim) for claim in settings.OIDC_STORE_CLAIMS + } + return { + "full_name": self.compute_full_name(user_info), + "short_name": user_info.get(settings.OIDC_USERINFO_SHORTNAME_FIELD), + "claims": claims_to_store, + } + + def get_existing_user(self, sub, email): + """Fetch existing user by sub or email.""" + + try: + return self.UserModel.objects.get_user_by_sub_or_email(sub, email) + except DuplicateEmailError as err: + raise SuspiciousOperation(err.message) from err diff --git a/src/backend/core/authentication/exceptions.py b/src/backend/core/authentication/exceptions.py new file mode 100644 index 0000000..c1c40cb --- /dev/null +++ b/src/backend/core/authentication/exceptions.py @@ -0,0 +1,5 @@ +"""Exceptions for the authentication module.""" + + +class UserCannotAccessApp(Exception): + """Exception raised when a user cannot access the app.""" diff --git a/src/backend/core/authentication/views.py b/src/backend/core/authentication/views.py new file mode 100644 index 0000000..96e4ad4 --- /dev/null +++ b/src/backend/core/authentication/views.py @@ -0,0 +1,25 @@ +"""Calendars core authentication views.""" + +from django.http import HttpResponseRedirect + +from lasuite.oidc_login.views import ( + OIDCAuthenticationCallbackView as LaSuiteOIDCAuthenticationCallbackView, +) + +from core.authentication.exceptions import UserCannotAccessApp + + +class OIDCAuthenticationCallbackView(LaSuiteOIDCAuthenticationCallbackView): + """ + Custom view for handling the authentication callback from the OpenID Connect (OIDC) provider. + Handles the callback after authentication from the identity provider (OP). + Verifies the state parameter and performs necessary authentication actions. + """ + + def get(self, request): + try: + return super().get(request) + except UserCannotAccessApp: + return HttpResponseRedirect( + self.failure_url + "?auth_error=user_cannot_access_app" + ) diff --git a/src/backend/core/enums.py b/src/backend/core/enums.py new file mode 100644 index 0000000..8f7e70c --- /dev/null +++ b/src/backend/core/enums.py @@ -0,0 +1,12 @@ +""" +Core application enums declaration +""" + +from django.conf import global_settings +from django.utils.translation import gettext_lazy as _ + +# In Django's code base, `LANGUAGES` is set by default with all supported languages. +# We can use it for the choice of languages which should not be limited to the few languages +# active in the app. +# pylint: disable=no-member +ALL_LANGUAGES = {language: _(name) for language, name in global_settings.LANGUAGES} diff --git a/src/backend/core/external_api/permissions.py b/src/backend/core/external_api/permissions.py new file mode 100644 index 0000000..6462e52 --- /dev/null +++ b/src/backend/core/external_api/permissions.py @@ -0,0 +1,41 @@ +"""Resource Server Permissions for the Calendars app.""" + +from django.conf import settings + +from lasuite.oidc_resource_server.authentication import ResourceServerAuthentication +from rest_framework import permissions + + +class ResourceServerClientPermission(permissions.BasePermission): + """ + Permission class for resource server views. + This provides a way to open the resource server views to a limited set of + Service Providers. + Note: we might add a more complex permission system in the future, based on + the Service Provider ID and the requested scopes. + """ + + def has_permission(self, request, view): + """ + Check if the user is authenticated and the token introspection + provides an authorized Service Provider. + """ + if not isinstance( + request.successful_authenticator, ResourceServerAuthentication + ): + # Not a resource server request + return False + + # Check if the user is authenticated + if not request.user.is_authenticated: + return False + if ( + hasattr(view, "resource_server_actions") + and view.action not in view.resource_server_actions + ): + return False + + # When used as a resource server, the request has a token audience + return ( + request.resource_server_token_audience in settings.OIDC_RS_ALLOWED_AUDIENCES + ) diff --git a/src/backend/core/external_api/viewsets.py b/src/backend/core/external_api/viewsets.py new file mode 100644 index 0000000..1d6e4c7 --- /dev/null +++ b/src/backend/core/external_api/viewsets.py @@ -0,0 +1,36 @@ +"""Resource Server Viewsets for the Calendars app.""" + +from django.conf import settings + +from lasuite.oidc_resource_server.authentication import ResourceServerAuthentication + +from core.api.permissions import AccessPermission, IsSelf +from core.api.viewsets import UserViewSet +from core.external_api.permissions import ResourceServerClientPermission + +# pylint: disable=too-many-ancestors + + +class ResourceServerRestrictionMixin: + """ + Mixin for Resource Server Viewsets to provide shortcut to get + configured actions for a given resource. + """ + + def _get_resource_server_actions(self, resource_name): + """Get resource_server_actions from settings.""" + external_api_config = settings.EXTERNAL_API.get(resource_name, {}) + return list(external_api_config.get("actions", [])) + + +class ResourceServerUserViewSet(ResourceServerRestrictionMixin, UserViewSet): + """Resource Server Viewset for the Calendars app.""" + + authentication_classes = [ResourceServerAuthentication] + + permission_classes = [ResourceServerClientPermission & IsSelf] + + @property + def resource_server_actions(self): + """Get resource_server_actions from settings.""" + return self._get_resource_server_actions("users") diff --git a/src/backend/core/factories.py b/src/backend/core/factories.py new file mode 100644 index 0000000..8b9a0f7 --- /dev/null +++ b/src/backend/core/factories.py @@ -0,0 +1,28 @@ +""" +Core application factories +""" + +from django.conf import settings +from django.contrib.auth.hashers import make_password + +import factory.fuzzy +from faker import Faker + +from core import models + +fake = Faker() + + +class UserFactory(factory.django.DjangoModelFactory): + """A factory to random users for testing purposes.""" + + class Meta: + model = models.User + skip_postgeneration_save = True + + sub = factory.Sequence(lambda n: f"user{n!s}") + email = factory.Faker("email") + full_name = factory.Faker("name") + short_name = factory.Faker("first_name") + language = factory.fuzzy.FuzzyChoice([lang[0] for lang in settings.LANGUAGES]) + password = make_password("password") diff --git a/src/backend/core/management/commands/__init__.py b/src/backend/core/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/management/commands/createsuperuser.py b/src/backend/core/management/commands/createsuperuser.py new file mode 100644 index 0000000..e45649e --- /dev/null +++ b/src/backend/core/management/commands/createsuperuser.py @@ -0,0 +1,47 @@ +"""Management user to create a superuser.""" + +from django.contrib.auth import get_user_model +from django.core.management.base import BaseCommand + +UserModel = get_user_model() + + +class Command(BaseCommand): + """Management command to create a superuser from an email and password.""" + + help = "Create a superuser with an email and a password" + + def add_arguments(self, parser): + """Define required arguments "email" and "password".""" + parser.add_argument( + "--email", + help=("Email for the user."), + ) + parser.add_argument( + "--password", + help="Password for the user.", + ) + + def handle(self, *args, **options): + """ + Given an email and a password, create a superuser or upgrade the existing + user to superuser status. + """ + email = options.get("email") + try: + user = UserModel.objects.get(admin_email=email) + except UserModel.DoesNotExist: + user = UserModel(admin_email=email) + message = "Superuser created successfully." + else: + if user.is_superuser and user.is_staff: + message = "Superuser already exists." + else: + message = "User already existed and was upgraded to superuser." + + user.is_superuser = True + user.is_staff = True + user.set_password(options["password"]) + user.save() + + self.stdout.write(self.style.SUCCESS(message)) diff --git a/src/backend/core/migrations/0001_initial.py b/src/backend/core/migrations/0001_initial.py new file mode 100644 index 0000000..f22e6ea --- /dev/null +++ b/src/backend/core/migrations/0001_initial.py @@ -0,0 +1,90 @@ +# Generated by Django 5.2.9 on 2026-01-08 23:49 + +import core.models +import django.core.validators +import django.db.models.deletion +import timezone_field.fields +import uuid +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='primary key for the record as UUID', primary_key=True, serialize=False, verbose_name='id')), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='date and time at which a record was created', verbose_name='created on')), + ('updated_at', models.DateTimeField(auto_now=True, help_text='date and time at which a record was last updated', verbose_name='updated on')), + ('sub', models.CharField(blank=True, help_text='Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: characters only.', max_length=255, null=True, unique=True, validators=[django.core.validators.RegexValidator(message='Enter a valid sub. This value may contain only letters, numbers, and @/./+/-/_/: characters.', regex='^[\\w.@+-:]+\\Z')], verbose_name='sub')), + ('full_name', models.CharField(blank=True, max_length=100, null=True, verbose_name='full name')), + ('short_name', models.CharField(blank=True, max_length=20, null=True, verbose_name='short name')), + ('email', models.EmailField(blank=True, max_length=254, null=True, verbose_name='identity email address')), + ('admin_email', models.EmailField(blank=True, max_length=254, null=True, unique=True, verbose_name='admin email address')), + ('language', models.CharField(blank=True, choices=[('en-us', 'English'), ('fr-fr', 'French'), ('de-de', 'German'), ('nl-nl', 'Dutch')], default=None, help_text='The language in which the user wants to see the interface.', max_length=10, null=True, verbose_name='language')), + ('timezone', timezone_field.fields.TimeZoneField(choices_display='WITH_GMT_OFFSET', default='UTC', help_text='The timezone in which the user wants to see times.', use_pytz=False)), + ('is_device', models.BooleanField(default=False, help_text='Whether the user is a device or a real user.', verbose_name='device')), + ('is_staff', models.BooleanField(default=False, help_text='Whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('claims', models.JSONField(blank=True, default=dict, help_text='Claims from the OIDC token.')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'db_table': 'calendars_user', + }, + managers=[ + ('objects', core.models.UserManager()), + ], + ), + migrations.CreateModel( + name='Calendar', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255)), + ('color', models.CharField(default='#3174ad', max_length=7)), + ('description', models.TextField(blank=True, default='')), + ('is_default', models.BooleanField(default=False)), + ('is_visible', models.BooleanField(default=True)), + ('davical_path', models.CharField(max_length=512, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='calendars', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-is_default', 'name'], + }, + ), + migrations.CreateModel( + name='CalendarShare', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('permission', models.CharField(choices=[('read', 'Read only'), ('write', 'Read and write')], default='read', max_length=10)), + ('is_visible', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('calendar', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shares', to='core.calendar')), + ('shared_with', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shared_calendars', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddConstraint( + model_name='calendar', + constraint=models.UniqueConstraint(condition=models.Q(('is_default', True)), fields=('owner',), name='unique_default_calendar_per_user'), + ), + migrations.AlterUniqueTogether( + name='calendarshare', + unique_together={('calendar', 'shared_with')}, + ), + ] diff --git a/src/backend/core/migrations/__init__.py b/src/backend/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/models.py b/src/backend/core/models.py new file mode 100644 index 0000000..3fc9df1 --- /dev/null +++ b/src/backend/core/models.py @@ -0,0 +1,402 @@ +""" +Declare and configure the models for the calendars core application +""" +# pylint: disable=too-many-lines + +import uuid +from datetime import timedelta +from logging import getLogger + +from django.conf import settings +from django.contrib.auth import models as auth_models +from django.contrib.auth.base_user import AbstractBaseUser +from django.contrib.postgres.indexes import GistIndex +from django.contrib.sites.models import Site +from django.core import mail, validators +from django.core.cache import cache +from django.core.exceptions import ValidationError +from django.core.mail import send_mail +from django.db import models, transaction +from django.db.models.expressions import RawSQL +from django.template.loader import render_to_string +from django.utils import timezone +from django.utils.functional import cached_property +from django.utils.translation import get_language, override +from django.utils.translation import gettext_lazy as _ + +from timezone_field import TimeZoneField + +logger = getLogger(__name__) + + +class LinkRoleChoices(models.TextChoices): + """Defines the possible roles a link can offer on a item.""" + + READER = "reader", _("Reader") # Can read + EDITOR = "editor", _("Editor") # Can read and edit + + +class RoleChoices(models.TextChoices): + """Defines the possible roles a user can have in a resource.""" + + READER = "reader", _("Reader") # Can read + EDITOR = "editor", _("Editor") # Can read and edit + ADMIN = "administrator", _("Administrator") # Can read, edit, delete and share + OWNER = "owner", _("Owner") + + +PRIVILEGED_ROLES = [RoleChoices.ADMIN, RoleChoices.OWNER] + + +class LinkReachChoices(models.TextChoices): + """Defines types of access for links""" + + RESTRICTED = ( + "restricted", + _("Restricted"), + ) # Only users with a specific access can read/edit the item + AUTHENTICATED = ( + "authenticated", + _("Authenticated"), + ) # Any authenticated user can access the item + PUBLIC = "public", _("Public") # Even anonymous users can access the item + + +class DuplicateEmailError(Exception): + """Raised when an email is already associated with a pre-existing user.""" + + def __init__(self, message=None, email=None): + """Set message and email to describe the exception.""" + self.message = message + self.email = email + super().__init__(self.message) + + +class BaseModel(models.Model): + """ + Serves as an abstract base model for other models, ensuring that records are validated + before saving as Django doesn't do it by default. + + Includes fields common to all models: a UUID primary key and creation/update timestamps. + """ + + id = models.UUIDField( + verbose_name=_("id"), + help_text=_("primary key for the record as UUID"), + primary_key=True, + default=uuid.uuid4, + editable=False, + ) + created_at = models.DateTimeField( + verbose_name=_("created on"), + help_text=_("date and time at which a record was created"), + auto_now_add=True, + editable=False, + ) + updated_at = models.DateTimeField( + verbose_name=_("updated on"), + help_text=_("date and time at which a record was last updated"), + auto_now=True, + editable=False, + ) + + class Meta: + abstract = True + + def save(self, *args, **kwargs): + """Call `full_clean` before saving.""" + self.full_clean() + super().save(*args, **kwargs) + + +class UserManager(auth_models.UserManager): + """Custom manager for User model with additional methods.""" + + def get_user_by_sub_or_email(self, sub, email): + """Fetch existing user by sub or email.""" + try: + return self.get(sub=sub) + except self.model.DoesNotExist as err: + if not email: + return None + + if settings.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION: + try: + return self.get(email=email) + except self.model.DoesNotExist: + pass + elif ( + self.filter(email=email).exists() + and not settings.OIDC_ALLOW_DUPLICATE_EMAILS + ): + raise DuplicateEmailError( + _( + "We couldn't find a user with this sub but the email is already " + "associated with a registered user." + ) + ) from err + return None + + +class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin): + """User model to work with OIDC only authentication.""" + + sub_validator = validators.RegexValidator( + regex=r"^[\w.@+-:]+\Z", + message=_( + "Enter a valid sub. This value may contain only letters, " + "numbers, and @/./+/-/_/: characters." + ), + ) + + sub = models.CharField( + _("sub"), + help_text=_( + "Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: characters only." + ), + max_length=255, + unique=True, + validators=[sub_validator], + blank=True, + null=True, + ) + + full_name = models.CharField(_("full name"), max_length=100, null=True, blank=True) + short_name = models.CharField(_("short name"), max_length=20, null=True, blank=True) + + email = models.EmailField(_("identity email address"), blank=True, null=True) + + # Unlike the "email" field which stores the email coming from the OIDC token, this field + # stores the email used by staff users to login to the admin site + admin_email = models.EmailField( + _("admin email address"), unique=True, blank=True, null=True + ) + + language = models.CharField( + max_length=10, + choices=settings.LANGUAGES, + default=None, + verbose_name=_("language"), + help_text=_("The language in which the user wants to see the interface."), + null=True, + blank=True, + ) + timezone = TimeZoneField( + choices_display="WITH_GMT_OFFSET", + use_pytz=False, + default=settings.TIME_ZONE, + help_text=_("The timezone in which the user wants to see times."), + ) + is_device = models.BooleanField( + _("device"), + default=False, + help_text=_("Whether the user is a device or a real user."), + ) + is_staff = models.BooleanField( + _("staff status"), + default=False, + help_text=_("Whether the user can log into this admin site."), + ) + is_active = models.BooleanField( + _("active"), + default=True, + help_text=_( + "Whether this user should be treated as active. " + "Unselect this instead of deleting accounts." + ), + ) + + claims = models.JSONField( + blank=True, + default=dict, + help_text=_("Claims from the OIDC token."), + ) + + objects = UserManager() + + USERNAME_FIELD = "admin_email" + REQUIRED_FIELDS = [] + + class Meta: + db_table = "calendars_user" + verbose_name = _("user") + verbose_name_plural = _("users") + + def __str__(self): + return self.email or self.admin_email or str(self.id) + + def save(self, *args, **kwargs): + """ + If it's a new user, give its user access to the items to which s.he was invited. + """ + is_adding = self._state.adding + + super().save(*args, **kwargs) + + def email_user(self, subject, message, from_email=None, **kwargs): + """Email this user.""" + if not self.email: + raise ValueError("User has no email address.") + mail.send_mail(subject, message, from_email, [self.email], **kwargs) + + @cached_property + def teams(self): + """ + Get list of teams in which the user is, as a list of strings. + Must be cached if retrieved remotely. + """ + return [] + + +class BaseAccess(BaseModel): + """Base model for accesses to handle resources.""" + + user = models.ForeignKey( + User, + on_delete=models.CASCADE, + null=True, + blank=True, + ) + team = models.CharField(max_length=100, blank=True) + role = models.CharField( + max_length=20, choices=RoleChoices.choices, default=RoleChoices.READER + ) + + class Meta: + abstract = True + + def _get_abilities(self, resource, user): + """ + Compute and return abilities for a given user taking into account + the current state of the object. + """ + roles = [] + if user.is_authenticated: + teams = user.teams + try: + roles = self.user_roles or [] + except AttributeError: + try: + roles = resource.accesses.filter( + models.Q(user=user) | models.Q(team__in=teams), + ).values_list("role", flat=True) + except (self._meta.model.DoesNotExist, IndexError): + roles = [] + + is_owner_or_admin = bool( + set(roles).intersection({RoleChoices.OWNER, RoleChoices.ADMIN}) + ) + if self.role == RoleChoices.OWNER: + can_delete = ( + RoleChoices.OWNER in roles + and resource.accesses.filter(role=RoleChoices.OWNER).count() > 1 + ) + set_role_to = ( + [RoleChoices.ADMIN, RoleChoices.EDITOR, RoleChoices.READER] + if can_delete + else [] + ) + else: + can_delete = is_owner_or_admin + set_role_to = [] + if RoleChoices.OWNER in roles: + set_role_to.append(RoleChoices.OWNER) + if is_owner_or_admin: + set_role_to.extend( + [RoleChoices.ADMIN, RoleChoices.EDITOR, RoleChoices.READER] + ) + + # Remove the current role as we don't want to propose it as an option + try: + set_role_to.remove(self.role) + except ValueError: + pass + + return { + "destroy": can_delete, + "update": bool(set_role_to), + "partial_update": bool(set_role_to), + "retrieve": bool(roles), + "set_role_to": set_role_to, + } + + +class Calendar(models.Model): + """ + Represents a calendar owned by a user. + This model tracks calendars stored in DAViCal and links them to Django users. + """ + + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name="calendars", + ) + name = models.CharField(max_length=255) + color = models.CharField(max_length=7, default="#3174ad") # Hex color + description = models.TextField(blank=True, default="") + is_default = models.BooleanField(default=False) + is_visible = models.BooleanField(default=True) + + # DAViCal reference - the calendar path in DAViCal + davical_path = models.CharField(max_length=512, unique=True) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + class Meta: + """Meta options for Calendar model.""" + + ordering = ["-is_default", "name"] + constraints = [ + models.UniqueConstraint( + fields=["owner"], + condition=models.Q(is_default=True), + name="unique_default_calendar_per_user", + ) + ] + + def __str__(self): + return f"{self.name} ({self.owner.email})" + + +class CalendarShare(models.Model): + """ + Represents a calendar shared with another user. + """ + + PERMISSION_READ = "read" + PERMISSION_WRITE = "write" + PERMISSION_CHOICES = [ + (PERMISSION_READ, "Read only"), + (PERMISSION_WRITE, "Read and write"), + ] + + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + calendar = models.ForeignKey( + Calendar, + on_delete=models.CASCADE, + related_name="shares", + ) + shared_with = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name="shared_calendars", + ) + permission = models.CharField( + max_length=10, + choices=PERMISSION_CHOICES, + default=PERMISSION_READ, + ) + is_visible = models.BooleanField(default=True) + + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + """Meta options for CalendarShare model.""" + + unique_together = ["calendar", "shared_with"] + + def __str__(self): + return f"{self.calendar.name} shared with {self.shared_with.email}" diff --git a/src/backend/core/services/__init__.py b/src/backend/core/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/services/caldav_service.py b/src/backend/core/services/caldav_service.py new file mode 100644 index 0000000..405be4b --- /dev/null +++ b/src/backend/core/services/caldav_service.py @@ -0,0 +1,477 @@ +"""Services for CalDAV integration with DAViCal.""" + +import logging +from datetime import date, datetime, timedelta +from typing import Optional +from uuid import uuid4 + +from django.conf import settings +from django.utils import timezone + +import psycopg + +from caldav import DAVClient +from caldav.lib.error import NotFoundError +from core.models import Calendar + +logger = logging.getLogger(__name__) + + +class DAViCalClient: + """ + Client for communicating with DAViCal CalDAV server using the caldav library. + """ + + def __init__(self): + self.base_url = getattr(settings, "DAVICAL_URL", "http://davical:80") + self.timeout = 30 + + def _get_client(self, user) -> DAVClient: + """ + Get a CalDAV client for the given user. + + DAViCal uses X-Forwarded-User header for authentication. The caldav + library requires username/password for Basic Auth, but DAViCal users have + password '*' (external auth). We pass the X-Forwarded-User header directly + to the DAVClient constructor. + """ + # DAViCal base URL - the caldav library will discover the principal + caldav_url = f"{self.base_url}/caldav.php/" + + return DAVClient( + url=caldav_url, + username=user.email, + password="", # Empty password - DAViCal uses X-Forwarded-User header + timeout=self.timeout, + headers={ + "X-Forwarded-User": user.email, + }, + ) + + def ensure_user_exists(self, user) -> None: + """ + Ensure the user exists in DAViCal's database. + Creates the user if they don't exist. + """ + # Connect to shared calendars database (public schema) + default_db = settings.DATABASES["default"] + db_name = default_db.get("NAME", "calendars") + + # Get password - handle SecretValue objects + password = default_db.get("PASSWORD", "pass") + if hasattr(password, "value"): + password = password.value + + # Connect to calendars database + conn = psycopg.connect( + host=default_db.get("HOST", "localhost"), + port=default_db.get("PORT", 5432), + dbname=db_name, + user=default_db.get("USER", "pgroot"), + password=password, + ) + + try: + with conn.cursor() as cursor: + # Check if user exists (in public schema) + cursor.execute( + "SELECT user_no FROM usr WHERE lower(username) = lower(%s)", + [user.email], + ) + if cursor.fetchone(): + # User already exists + return + + # Create user in DAViCal (public schema) + # Use email as username, password '*' means external auth + # Get user's full name or use email prefix + fullname = ( + getattr(user, "full_name", None) + or getattr(user, "get_full_name", lambda: None)() + or user.email.split("@")[0] + ) + + cursor.execute( + """ + INSERT INTO usr (username, email, fullname, active, password) + VALUES (%s, %s, %s, true, '*') + ON CONFLICT (lower(username)) DO NOTHING + RETURNING user_no + """, + [user.email, user.email, fullname], + ) + result = cursor.fetchone() + if result: + user_no = result[0] + logger.info( + "Created DAViCal user: %s (user_no: %s)", user.email, user_no + ) + + # Also create a principal record for the user (public schema) + # DAViCal needs both usr and principal records + # Principal type 1 is for users + type_id = 1 + + cursor.execute( + """ + INSERT INTO principal (type_id, user_no, displayname) + SELECT %s, %s, %s + WHERE NOT EXISTS (SELECT 1 FROM principal WHERE user_no = %s) + RETURNING principal_id + """, + [type_id, user_no, fullname, user_no], + ) + principal_result = cursor.fetchone() + if principal_result: + logger.info( + "Created DAViCal principal: %s (principal_id: %s)", + user.email, + principal_result[0], + ) + else: + logger.warning("User %s already exists in DAViCal", user.email) + conn.commit() + finally: + conn.close() + + def create_calendar(self, user, calendar_name: str, calendar_id: str) -> str: + """ + Create a new calendar in DAViCal for the given user. + Returns the DAViCal path for the calendar. + """ + # Ensure user exists first + self.ensure_user_exists(user) + + client = self._get_client(user) + principal = client.principal() + + try: + # Create calendar using caldav library + calendar = principal.make_calendar(name=calendar_name) + + # DAViCal calendar path format: /caldav.php/{username}/{calendar_id}/ + # The caldav library returns a URL object, convert to string and extract path + calendar_url = str(calendar.url) + # Extract path from full URL + if calendar_url.startswith(self.base_url): + path = calendar_url[len(self.base_url) :] + else: + # Fallback: construct path manually based on DAViCal's structure + # DAViCal creates calendars with a specific path structure + path = f"/caldav.php/{user.email}/{calendar_id}/" + + logger.info("Created calendar in DAViCal: %s at %s", calendar_name, path) + return path + except Exception as e: + logger.error("Failed to create calendar in DAViCal: %s", str(e)) + raise + + def get_events( + self, + user, + calendar_path: str, + start: Optional[datetime] = None, + end: Optional[datetime] = None, + ) -> list: + """ + Get events from a calendar within a time range. + Returns list of event dictionaries with parsed data. + """ + # Ensure user exists first + self.ensure_user_exists(user) + + # Default to current month if no range specified + if start is None: + start = timezone.now().replace(day=1, hour=0, minute=0, second=0) + if end is None: + end = start + timedelta(days=31) + + client = self._get_client(user) + + # Get calendar by URL + calendar_url = f"{self.base_url}{calendar_path}" + calendar = client.calendar(url=calendar_url) + + try: + # Search for events in the date range + # Convert datetime to date for search if needed + start_date = start.date() if isinstance(start, datetime) else start + end_date = end.date() if isinstance(end, datetime) else end + + events = calendar.search( + event=True, + start=start_date, + end=end_date, + expand=True, # Expand recurring events + ) + + # Parse events into dictionaries + parsed_events = [] + for event in events: + event_data = self._parse_event(event) + if event_data: + parsed_events.append(event_data) + + return parsed_events + except NotFoundError: + logger.warning("Calendar not found at path: %s", calendar_path) + return [] + except Exception as e: + logger.error("Failed to get events from DAViCal: %s", str(e)) + raise + + def create_event(self, user, calendar_path: str, event_data: dict) -> str: + """ + Create a new event in DAViCal. + Returns the event UID. + """ + # Ensure user exists first + self.ensure_user_exists(user) + + client = self._get_client(user) + calendar_url = f"{self.base_url}{calendar_path}" + calendar = client.calendar(url=calendar_url) + + # Extract event data + dtstart = event_data.get("start", timezone.now()) + dtend = event_data.get("end", dtstart + timedelta(hours=1)) + summary = event_data.get("title", "New Event") + description = event_data.get("description", "") + location = event_data.get("location", "") + + # Generate UID if not provided + event_uid = event_data.get("uid", str(uuid4())) + + try: + # Create event using caldav library + event = calendar.save_event( + dtstart=dtstart, + dtend=dtend, + uid=event_uid, + summary=summary, + description=description, + location=location, + ) + + # Extract UID from created event + # The caldav library returns an Event object + if hasattr(event, "icalendar_component"): + event_uid = str(event.icalendar_component.get("uid", event_uid)) + elif hasattr(event, "vobject_instance"): + event_uid = event.vobject_instance.vevent.uid.value + + logger.info("Created event in DAViCal: %s", event_uid) + return event_uid + except Exception as e: + logger.error("Failed to create event in DAViCal: %s", str(e)) + raise + + def update_event( + self, user, calendar_path: str, event_uid: str, event_data: dict + ) -> None: + """Update an existing event in DAViCal.""" + # Ensure user exists first + self.ensure_user_exists(user) + + client = self._get_client(user) + calendar_url = f"{self.base_url}{calendar_path}" + calendar = client.calendar(url=calendar_url) + + try: + # Search for the event by UID + events = calendar.search(event=True) + target_event = None + + for event in events: + event_uid_value = None + if hasattr(event, "icalendar_component"): + event_uid_value = str(event.icalendar_component.get("uid", "")) + elif hasattr(event, "vobject_instance"): + event_uid_value = event.vobject_instance.vevent.uid.value + + if event_uid_value == event_uid: + target_event = event + break + + if not target_event: + raise ValueError(f"Event with UID {event_uid} not found") + + # Update event properties + dtstart = event_data.get("start") + dtend = event_data.get("end") + summary = event_data.get("title") + description = event_data.get("description") + location = event_data.get("location") + + # Update using icalendar component + component = target_event.icalendar_component + + if dtstart: + component["dtstart"] = dtstart + if dtend: + component["dtend"] = dtend + if summary: + component["summary"] = summary + if description is not None: + component["description"] = description + if location is not None: + component["location"] = location + + # Save the updated event + target_event.save() + + logger.info("Updated event in DAViCal: %s", event_uid) + except Exception as e: + logger.error("Failed to update event in DAViCal: %s", str(e)) + raise + + def delete_event(self, user, calendar_path: str, event_uid: str) -> None: + """Delete an event from DAViCal.""" + # Ensure user exists first + self.ensure_user_exists(user) + + client = self._get_client(user) + calendar_url = f"{self.base_url}{calendar_path}" + calendar = client.calendar(url=calendar_url) + + try: + # Search for the event by UID + events = calendar.search(event=True) + target_event = None + + for event in events: + event_uid_value = None + if hasattr(event, "icalendar_component"): + event_uid_value = str(event.icalendar_component.get("uid", "")) + elif hasattr(event, "vobject_instance"): + event_uid_value = event.vobject_instance.vevent.uid.value + + if event_uid_value == event_uid: + target_event = event + break + + if not target_event: + raise ValueError(f"Event with UID {event_uid} not found") + + # Delete the event + target_event.delete() + + logger.info("Deleted event from DAViCal: %s", event_uid) + except Exception as e: + logger.error("Failed to delete event from DAViCal: %s", str(e)) + raise + + def _parse_event(self, event) -> Optional[dict]: + """ + Parse a caldav Event object and return event data as dictionary. + """ + try: + component = event.icalendar_component + + event_data = { + "uid": str(component.get("uid", "")), + "title": str(component.get("summary", "")), + "start": component.get("dtstart").dt + if component.get("dtstart") + else None, + "end": component.get("dtend").dt if component.get("dtend") else None, + "description": str(component.get("description", "")), + "location": str(component.get("location", "")), + } + + # Convert datetime to string format for consistency + if event_data["start"]: + if isinstance(event_data["start"], datetime): + event_data["start"] = event_data["start"].strftime("%Y%m%dT%H%M%SZ") + elif isinstance(event_data["start"], date): + event_data["start"] = event_data["start"].strftime("%Y%m%d") + + if event_data["end"]: + if isinstance(event_data["end"], datetime): + event_data["end"] = event_data["end"].strftime("%Y%m%dT%H%M%SZ") + elif isinstance(event_data["end"], date): + event_data["end"] = event_data["end"].strftime("%Y%m%d") + + return event_data if event_data.get("uid") else None + except Exception as e: + logger.warning("Failed to parse event: %s", str(e)) + return None + + +class CalendarService: + """ + High-level service for managing calendars and events. + """ + + def __init__(self): + self.davical = DAViCalClient() + + def create_default_calendar(self, user) -> Calendar: + """ + Create a default calendar for a user. + """ + calendar_id = str(uuid4()) + calendar_name = "Mon calendrier" + + # Create calendar in DAViCal + davical_path = self.davical.create_calendar(user, calendar_name, calendar_id) + + # Create local Calendar record + calendar = Calendar.objects.create( + owner=user, + name=calendar_name, + davical_path=davical_path, + is_default=True, + color="#3174ad", + ) + + return calendar + + def create_calendar(self, user, name: str, color: str = "#3174ad") -> Calendar: + """ + Create a new calendar for a user. + """ + calendar_id = str(uuid4()) + + # Create calendar in DAViCal + davical_path = self.davical.create_calendar(user, name, calendar_id) + + # Create local Calendar record + calendar = Calendar.objects.create( + owner=user, + name=name, + davical_path=davical_path, + is_default=False, + color=color, + ) + + return calendar + + def get_user_calendars(self, user): + """ + Get all calendars accessible by a user (owned + shared). + """ + owned = Calendar.objects.filter(owner=user) + shared = Calendar.objects.filter(shares__shared_with=user) + return owned.union(shared) + + def get_events(self, user, calendar: Calendar, start=None, end=None) -> list: + """ + Get events from a calendar. + Returns parsed event data. + """ + return self.davical.get_events(user, calendar.davical_path, start, end) + + def create_event(self, user, calendar: Calendar, event_data: dict) -> str: + """Create a new event.""" + return self.davical.create_event(user, calendar.davical_path, event_data) + + def update_event( + self, user, calendar: Calendar, event_uid: str, event_data: dict + ) -> None: + """Update an existing event.""" + self.davical.update_event(user, calendar.davical_path, event_uid, event_data) + + def delete_event(self, user, calendar: Calendar, event_uid: str) -> None: + """Delete an event.""" + self.davical.delete_event(user, calendar.davical_path, event_uid) diff --git a/src/backend/core/signals.py b/src/backend/core/signals.py new file mode 100644 index 0000000..ee9266c --- /dev/null +++ b/src/backend/core/signals.py @@ -0,0 +1,55 @@ +""" +Declare and configure the signals for the calendars core application +""" + +import logging + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.db.models.signals import post_save +from django.dispatch import receiver + +from core.services.caldav_service import CalendarService + +logger = logging.getLogger(__name__) +User = get_user_model() + + +@receiver(post_save, sender=User) +def provision_default_calendar(sender, instance, created, **kwargs): + """ + Auto-provision a default calendar when a new user is created. + """ + if not created: + return + + # Check if user already has a default calendar + if instance.calendars.filter(is_default=True).exists(): + return + + # Skip calendar creation if DAViCal is not configured + if not getattr(settings, "DAVICAL_URL", None): + return + + try: + service = CalendarService() + service.create_default_calendar(instance) + logger.info("Created default calendar for user %s", instance.email) + except Exception as e: + # In tests, DAViCal tables don't exist, so fail silently + # Check if it's a database error that suggests we're in tests + error_str = str(e).lower() + if "does not exist" in error_str or "relation" in error_str: + # Likely in test environment, fail silently + logger.debug( + "Skipped calendar creation for user %s (likely test environment): %s", + instance.email, + str(e), + ) + else: + # Real error, log it + logger.error( + "Failed to create default calendar for user %s: %s", + instance.email, + str(e), + ) diff --git a/src/backend/core/templatetags/__init__.py b/src/backend/core/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/templatetags/extra_tags.py b/src/backend/core/templatetags/extra_tags.py new file mode 100644 index 0000000..37ab50b --- /dev/null +++ b/src/backend/core/templatetags/extra_tags.py @@ -0,0 +1,58 @@ +"""Custom template tags for the calendars core application.""" + +import base64 + +from django import template +from django.contrib.staticfiles import finders + +from PIL import ImageFile as PillowImageFile + +register = template.Library() + + +def image_to_base64(file_or_path, close=False): + """ + Return the src string of the base64 encoding of an image represented by its path + or file opened or not. + + Inspired by Django's "get_image_dimensions" + """ + pil_parser = PillowImageFile.Parser() + if hasattr(file_or_path, "read"): + file = file_or_path + if file.closed and hasattr(file, "open"): + file_or_path.open() + file_pos = file.tell() + file.seek(0) + else: + try: + # pylint: disable=consider-using-with + file = open(file_or_path, "rb") + except OSError: + return "" + close = True + + try: + image_data = file.read() + if not image_data: + return "" + pil_parser.feed(image_data) + if pil_parser.image: + mime_type = pil_parser.image.get_format_mimetype() + encoded_string = base64.b64encode(image_data) + return f"data:{mime_type:s};base64, {encoded_string.decode('utf-8'):s}" + return "" + finally: + if close: + file.close() + else: + file.seek(file_pos) + + +@register.simple_tag +def base64_static(path): + """Return a static file into a base64.""" + full_path = finders.find(path) + if full_path: + return image_to_base64(full_path, True) + return "" diff --git a/src/backend/core/tests/__init__.py b/src/backend/core/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/tests/authentication/__init__.py b/src/backend/core/tests/authentication/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/tests/authentication/test_backends.py b/src/backend/core/tests/authentication/test_backends.py new file mode 100644 index 0000000..1bda314 --- /dev/null +++ b/src/backend/core/tests/authentication/test_backends.py @@ -0,0 +1,579 @@ +"""Unit tests for the Authentication Backends.""" + +import random +import re +from unittest import mock + +from django.core.exceptions import SuspiciousOperation +from django.test.utils import override_settings + +import pytest +import responses +from cryptography.fernet import Fernet +from lasuite.oidc_login.backends import get_oidc_refresh_token + +from core import models +from core.authentication.backends import OIDCAuthenticationBackend +from core.authentication.exceptions import UserCannotAccessApp +from core.factories import UserFactory + +pytestmark = pytest.mark.django_db + + +def test_authentication_getter_existing_user_no_email( + django_assert_num_queries, monkeypatch +): + """ + If an existing user matches the user's info sub, the user should be returned. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory() + + def get_userinfo_mocked(*args): + return {"sub": db_user.sub} + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + with django_assert_num_queries(1): + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user == db_user + + +def test_authentication_getter_existing_user_via_email( + django_assert_num_queries, monkeypatch +): + """ + If an existing user doesn't match the sub but matches the email, + the user should be returned. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory() + + def get_userinfo_mocked(*args): + return {"sub": "123", "email": db_user.email} + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + with django_assert_num_queries(4): # user by sub, user by mail, update sub + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user == db_user + + +def test_authentication_getter_email_none(monkeypatch): + """ + If no user is found with the sub and no email is provided, a new user should be created. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory(email=None) + + def get_userinfo_mocked(*args): + user_info = {"sub": "123"} + if random.choice([True, False]): + user_info["email"] = None + return user_info + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + # Since the sub and email didn't match, it should create a new user + assert models.User.objects.count() == 2 + assert user != db_user + assert user.sub == "123" + + +def test_authentication_getter_existing_user_no_fallback_to_email_allow_duplicate( + settings, monkeypatch +): + """ + When the "OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION" setting is set to False, + the system should not match users by email, even if the email matches. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory() + + # Set the setting to False + settings.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION = False + settings.OIDC_ALLOW_DUPLICATE_EMAILS = True + + def get_userinfo_mocked(*args): + return {"sub": "123", "email": db_user.email} + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + # Since the sub doesn't match, it should create a new user + assert models.User.objects.count() == 2 + assert user != db_user + assert user.sub == "123" + + +def test_authentication_getter_existing_user_no_fallback_to_email_no_duplicate( + settings, monkeypatch +): + """ + When the "OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION" setting is set to False, + the system should not match users by email, even if the email matches. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory() + + # Set the setting to False + settings.OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION = False + settings.OIDC_ALLOW_DUPLICATE_EMAILS = False + + def get_userinfo_mocked(*args): + return {"sub": "123", "email": db_user.email} + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + with pytest.raises( + SuspiciousOperation, + match=( + "We couldn't find a user with this sub but the email is already associated " + "with a registered user." + ), + ): + klass.get_or_create_user(access_token="test-token", id_token=None, payload=None) + + # Since the sub doesn't match, it should not create a new user + assert models.User.objects.count() == 1 + + +def test_authentication_getter_existing_user_with_email( + django_assert_num_queries, monkeypatch +): + """ + When the user's info contains an email and targets an existing user, + """ + klass = OIDCAuthenticationBackend() + user = UserFactory(full_name="John Doe", short_name="John") + + def get_userinfo_mocked(*args): + return { + "sub": user.sub, + "email": user.email, + "first_name": "John", + "last_name": "Doe", + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + # Only 1 query because email and names have not changed + with django_assert_num_queries(1): + authenticated_user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user == authenticated_user + + +@pytest.mark.parametrize( + "first_name, last_name, email", + [ + ("Jack", "Doe", "john.doe@example.com"), + ("John", "Duy", "john.doe@example.com"), + ("John", "Doe", "jack.duy@example.com"), + ("Jack", "Duy", "jack.duy@example.com"), + ], +) +def test_authentication_getter_existing_user_change_fields_sub( + first_name, last_name, email, django_assert_num_queries, monkeypatch +): + """ + It should update the email or name fields on the user when they change + and the user was identified by its "sub". + """ + klass = OIDCAuthenticationBackend() + user = UserFactory( + full_name="John Doe", short_name="John", email="john.doe@example.com" + ) + + def get_userinfo_mocked(*args): + return { + "sub": user.sub, + "email": email, + "first_name": first_name, + "last_name": last_name, + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + # One and only one additional update query when a field has changed + with django_assert_num_queries(3): + authenticated_user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user == authenticated_user + user.refresh_from_db() + assert user.email == email + assert user.full_name == f"{first_name:s} {last_name:s}" + assert user.short_name == first_name + + +@pytest.mark.parametrize( + "first_name, last_name, email", + [ + ("Jack", "Doe", "john.doe@example.com"), + ("John", "Duy", "john.doe@example.com"), + ], +) +def test_authentication_getter_existing_user_change_fields_email( + first_name, last_name, email, django_assert_num_queries, monkeypatch +): + """ + It should update the name fields on the user when they change + and the user was identified by its "email" as fallback. + """ + klass = OIDCAuthenticationBackend() + user = UserFactory( + full_name="John Doe", short_name="John", email="john.doe@example.com" + ) + + def get_userinfo_mocked(*args): + return { + "sub": "123", + "email": user.email, + "first_name": first_name, + "last_name": last_name, + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + # One and only one additional update query when a field has changed + with django_assert_num_queries(4): + authenticated_user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user == authenticated_user + user.refresh_from_db() + assert user.email == email + assert user.full_name == f"{first_name:s} {last_name:s}" + assert user.short_name == first_name + + +def test_authentication_getter_new_user_no_email(monkeypatch): + """ + If no user matches the user's info sub, a user should be created. + User's info doesn't contain an email, created user's email should be empty. + """ + klass = OIDCAuthenticationBackend() + + def get_userinfo_mocked(*args): + return {"sub": "123"} + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user.sub == "123" + assert user.email is None + assert user.full_name is None + assert user.short_name is None + assert user.has_usable_password() is False + assert models.User.objects.count() == 1 + + +def test_authentication_getter_new_user_with_email(monkeypatch): + """ + If no user matches the user's info sub, a user should be created. + User's email and name should be set on the identity. + The "email" field on the User model should not be set as it is reserved for staff users. + """ + klass = OIDCAuthenticationBackend() + + email = "calendars@example.com" + + def get_userinfo_mocked(*args): + return {"sub": "123", "email": email, "first_name": "John", "last_name": "Doe"} + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user.sub == "123" + assert user.email == email + assert user.full_name == "John Doe" + assert user.short_name == "John" + assert user.has_usable_password() is False + assert models.User.objects.count() == 1 + + +@override_settings(OIDC_OP_USER_ENDPOINT="http://oidc.endpoint.test/userinfo") +@responses.activate +def test_authentication_get_userinfo_json_response(): + """Test get_userinfo method with a JSON response.""" + + responses.add( + responses.GET, + re.compile(r".*/userinfo"), + json={ + "first_name": "John", + "last_name": "Doe", + "email": "john.doe@example.com", + }, + status=200, + ) + + oidc_backend = OIDCAuthenticationBackend() + result = oidc_backend.get_userinfo("fake_access_token", None, None) + + assert result["first_name"] == "John" + assert result["last_name"] == "Doe" + assert result["email"] == "john.doe@example.com" + + +@override_settings(OIDC_OP_USER_ENDPOINT="http://oidc.endpoint.test/userinfo") +@responses.activate +def test_authentication_get_userinfo_token_response(monkeypatch, settings): + """Test get_userinfo method with a token response.""" + settings.OIDC_RP_SIGN_ALGO = "HS256" # disable JWKS URL call + responses.add( + responses.GET, + re.compile(r".*/userinfo"), + body="fake.jwt.token", + status=200, + content_type="application/jwt", + ) + + def mock_verify_token(self, token): # pylint: disable=unused-argument + return { + "first_name": "Jane", + "last_name": "Doe", + "email": "jane.doe@example.com", + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "verify_token", mock_verify_token) + + oidc_backend = OIDCAuthenticationBackend() + result = oidc_backend.get_userinfo("fake_access_token", None, None) + + assert result["first_name"] == "Jane" + assert result["last_name"] == "Doe" + assert result["email"] == "jane.doe@example.com" + + +@override_settings(OIDC_OP_USER_ENDPOINT="http://oidc.endpoint.test/userinfo") +@responses.activate +def test_authentication_get_userinfo_invalid_response(settings): + """ + Test get_userinfo method with an invalid JWT response that + causes verify_token to raise an error. + """ + settings.OIDC_RP_SIGN_ALGO = "HS256" # disable JWKS URL call + responses.add( + responses.GET, + re.compile(r".*/userinfo"), + body="fake.jwt.token", + status=200, + content_type="application/jwt", + ) + + oidc_backend = OIDCAuthenticationBackend() + + with pytest.raises( + SuspiciousOperation, + match="User info response was not valid JWT", + ): + oidc_backend.get_userinfo("fake_access_token", None, None) + + +def test_authentication_getter_existing_disabled_user_via_sub( + django_assert_num_queries, monkeypatch +): + """ + If an existing user matches the sub but is disabled, + an error should be raised and a user should not be created. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory(is_active=False) + + def get_userinfo_mocked(*args): + return { + "sub": db_user.sub, + "email": db_user.email, + "first_name": "John", + "last_name": "Doe", + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + with ( + django_assert_num_queries(1), + pytest.raises(SuspiciousOperation, match="User account is disabled"), + ): + klass.get_or_create_user(access_token="test-token", id_token=None, payload=None) + + assert models.User.objects.count() == 1 + + +def test_authentication_getter_existing_disabled_user_via_email( + django_assert_num_queries, monkeypatch +): + """ + If an existing user does not match the sub but matches the email and is disabled, + an error should be raised and a user should not be created. + """ + + klass = OIDCAuthenticationBackend() + db_user = UserFactory(is_active=False) + + def get_userinfo_mocked(*args): + return { + "sub": "random", + "email": db_user.email, + "first_name": "John", + "last_name": "Doe", + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + with ( + django_assert_num_queries(2), + pytest.raises(SuspiciousOperation, match="User account is disabled"), + ): + klass.get_or_create_user(access_token="test-token", id_token=None, payload=None) + + assert models.User.objects.count() == 1 + + +@responses.activate +def test_authentication_session_tokens( + django_assert_num_queries, monkeypatch, rf, settings +): + """ + Test that the session contains oidc_refresh_token and oidc_access_token after authentication. + """ + settings.OIDC_OP_TOKEN_ENDPOINT = "http://oidc.endpoint.test/token" + settings.OIDC_OP_USER_ENDPOINT = "http://oidc.endpoint.test/userinfo" + settings.OIDC_OP_JWKS_ENDPOINT = "http://oidc.endpoint.test/jwks" + settings.OIDC_STORE_ACCESS_TOKEN = True + settings.OIDC_STORE_REFRESH_TOKEN = True + settings.OIDC_STORE_REFRESH_TOKEN_KEY = Fernet.generate_key() + + klass = OIDCAuthenticationBackend() + request = rf.get("/some-url", {"state": "test-state", "code": "test-code"}) + request.session = {} + + def verify_token_mocked(*args, **kwargs): + return {"sub": "123", "email": "test@example.com"} + + monkeypatch.setattr(OIDCAuthenticationBackend, "verify_token", verify_token_mocked) + + responses.add( + responses.POST, + re.compile(settings.OIDC_OP_TOKEN_ENDPOINT), + json={ + "access_token": "test-access-token", + "refresh_token": "test-refresh-token", + }, + status=200, + ) + + responses.add( + responses.GET, + re.compile(settings.OIDC_OP_USER_ENDPOINT), + json={"sub": "123", "email": "test@example.com"}, + status=200, + ) + + with django_assert_num_queries(27): + user = klass.authenticate( + request, + code="test-code", + nonce="test-nonce", + code_verifier="test-code-verifier", + ) + + assert user is not None + assert request.session["oidc_access_token"] == "test-access-token" + assert get_oidc_refresh_token(request.session) == "test-refresh-token" + + +@override_settings(OIDC_STORE_CLAIMS=["iss"]) +def test_authentication_store_claims_new_user(monkeypatch): + """ + Test that the claims are stored on the user when a new user is created. + """ + klass = OIDCAuthenticationBackend() + + email = "calendars@example.com" + + def get_userinfo_mocked(*args): + return { + "sub": "123", + "email": email, + "first_name": "John", + "last_name": "Doe", + "iss": "https://example.com", + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + assert user.sub == "123" + assert user.email == email + assert user.full_name == "John Doe" + assert user.short_name == "John" + assert user.has_usable_password() is False + assert user.claims == {"iss": "https://example.com"} + assert models.User.objects.count() == 1 + + +@override_settings(OIDC_STORE_CLAIMS=["iss"]) +def test_authentication_store_claims_existing_user(monkeypatch): + """ + Test that the claims are stored on the user when an existing user is authenticated. + """ + klass = OIDCAuthenticationBackend() + user = UserFactory( + email="calendars@example.com", sub="123", claims={"iss": "https://obsolete.com"} + ) + email = "calendars@example.com" + + def get_userinfo_mocked(*args): + return { + "sub": "123", + "email": email, + "first_name": "John", + "last_name": "Doe", + "iss": "https://example.com", + } + + monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) + + user = klass.get_or_create_user( + access_token="test-token", id_token=None, payload=None + ) + + user.refresh_from_db() + assert user.sub == "123" + assert user.email == email + assert user.claims == {"iss": "https://example.com"} + assert models.User.objects.count() == 1 diff --git a/src/backend/core/tests/authentication/test_views.py b/src/backend/core/tests/authentication/test_views.py new file mode 100644 index 0000000..ebc92ba --- /dev/null +++ b/src/backend/core/tests/authentication/test_views.py @@ -0,0 +1,66 @@ +"""Unit tests for the Authentication Views.""" + +from unittest import mock + +from django.contrib.sessions.middleware import SessionMiddleware +from django.test import RequestFactory +from django.test.utils import override_settings + +import pytest +from mozilla_django_oidc.auth import ( + OIDCAuthenticationBackend as MozillaOIDCAuthenticationBackend, +) + +from core import factories +from core.authentication.backends import OIDCAuthenticationBackend +from core.authentication.views import ( + OIDCAuthenticationCallbackView, +) + +pytestmark = pytest.mark.django_db + + +@override_settings( + LOGIN_REDIRECT_URL_FAILURE="/auth/failure", + LOGIN_REDIRECT_URL="/auth/success", +) +@mock.patch.object( + MozillaOIDCAuthenticationBackend, + "get_token", + return_value={"id_token": "mocked_id_token", "access_token": "mocked_access_token"}, +) +@mock.patch.object( + MozillaOIDCAuthenticationBackend, "verify_token", return_value={"not": "needed"} +) +@mock.patch.object( + OIDCAuthenticationBackend, + "get_userinfo", + return_value={"sub": "mocked_sub", "email": "allowed@example.com"}, +) +def test_view_login_callback_authorized_by_default( + mocked_get_userinfo, mocked_verify_token, mocked_get_token +): + """By default, all users are authorized to login.""" + + user = factories.UserFactory(email="allowed@example.com") + + request = RequestFactory().get( + "/callback/", data={"state": "mocked_state", "code": "mocked_code"} + ) + request.user = user + + middleware = SessionMiddleware(get_response=lambda x: x) + middleware.process_request(request) + + mocked_state = "mocked_state" + request.session["oidc_states"] = {mocked_state: {"nonce": "mocked_nonce"}} + request.session.save() + + callback_view = OIDCAuthenticationCallbackView.as_view() + + response = callback_view(request) + mocked_get_token.assert_called_once() + mocked_verify_token.assert_called_once() + mocked_get_userinfo.assert_called_once() + assert response.status_code == 302 + assert response.url == "/auth/success" diff --git a/src/backend/core/tests/conftest.py b/src/backend/core/tests/conftest.py new file mode 100644 index 0000000..64c2a43 --- /dev/null +++ b/src/backend/core/tests/conftest.py @@ -0,0 +1,148 @@ +"""Fixtures for tests in the calendars core application""" + +import base64 +from unittest import mock + +from django.core.cache import cache +from django.db import connection + +import pytest +import responses +from cryptography.fernet import Fernet + +from core import factories +from core.tests.utils.urls import reload_urls + +USER = "user" +TEAM = "team" +VIA = [USER, TEAM] + + +@pytest.fixture(autouse=True) +def truncate_davical_tables(django_db_setup, django_db_blocker): + """Fixture to truncate DAViCal tables at the start of each test. + + DAViCal tables are created by the DAViCal container migrations, not Django. + We just truncate them to ensure clean state for each test. + """ + with django_db_blocker.unblock(): + with connection.cursor() as cursor: + # Truncate DAViCal tables if they exist (created by DAViCal container) + cursor.execute(""" + DO $$ + BEGIN + IF EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'principal') THEN + TRUNCATE TABLE principal CASCADE; + END IF; + IF EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'usr') THEN + TRUNCATE TABLE usr CASCADE; + END IF; + END $$; + """) + yield + + +@pytest.fixture(autouse=True) +def clear_cache(): + """Fixture to clear the cache after each test.""" + yield + cache.clear() + # Clear functools.cache for functions decorated with @functools.cache + + +@pytest.fixture +def mock_user_teams(): + """Mock for the "teams" property on the User model.""" + with mock.patch( + "core.models.User.teams", new_callable=mock.PropertyMock + ) as mock_teams: + yield mock_teams + + +def resource_server_backend_setup(settings): + """ + A fixture to create a user token for testing. + """ + assert ( + settings.OIDC_RS_BACKEND_CLASS + == "lasuite.oidc_resource_server.backend.ResourceServerBackend" + ) + + settings.OIDC_RESOURCE_SERVER_ENABLED = True + settings.OIDC_RS_CLIENT_ID = "some_client_id" + settings.OIDC_RS_CLIENT_SECRET = "some_client_secret" + + settings.OIDC_OP_URL = "https://oidc.example.com" + settings.OIDC_VERIFY_SSL = False + settings.OIDC_TIMEOUT = 5 + settings.OIDC_PROXY = None + settings.OIDC_OP_JWKS_ENDPOINT = "https://oidc.example.com/jwks" + settings.OIDC_OP_INTROSPECTION_ENDPOINT = "https://oidc.example.com/introspect" + settings.OIDC_RS_SCOPES = ["openid", "groups"] + settings.OIDC_RS_ALLOWED_AUDIENCES = ["some_service_provider"] + + +@pytest.fixture +def resource_server_backend_conf(settings): + """ + A fixture to create a user token for testing. + """ + resource_server_backend_setup(settings) + reload_urls() + + +@pytest.fixture +def resource_server_backend(settings): + """ + A fixture to create a user token for testing. + Including a mocked introspection endpoint. + """ + resource_server_backend_setup(settings) + reload_urls() + + with responses.RequestsMock() as rsps: + rsps.add( + responses.POST, + "https://oidc.example.com/introspect", + json={ + "iss": "https://oidc.example.com", + "aud": "some_client_id", # settings.OIDC_RS_CLIENT_ID + "sub": "very-specific-sub", + "client_id": "some_service_provider", + "scope": "openid groups", + "active": True, + }, + ) + + yield rsps + + +@pytest.fixture +def user_specific_sub(): + """ + A fixture to create a user token for testing. + """ + user = factories.UserFactory(sub="very-specific-sub") + + yield user + + +def build_authorization_bearer(token): + """ + Build an Authorization Bearer header value from a token. + + This can be used like this: + client.post( + ... + HTTP_AUTHORIZATION=f"Bearer {build_authorization_bearer('some_token')}", + ) + """ + return base64.b64encode(token.encode("utf-8")).decode("utf-8") + + +@pytest.fixture +def user_token(): + """ + A fixture to create a user token for testing. + """ + return build_authorization_bearer("some_token") diff --git a/src/backend/core/tests/external_api/test_external_api_users.py b/src/backend/core/tests/external_api/test_external_api_users.py new file mode 100644 index 0000000..b59dc07 --- /dev/null +++ b/src/backend/core/tests/external_api/test_external_api_users.py @@ -0,0 +1,152 @@ +""" +Tests for the Resource Server API for users. + +Not testing external API endpoints that are already tested in the /api +because the resource server viewsets inherit from the api viewsets. + +""" + +import pytest +from rest_framework.test import APIClient + +from core import factories +from core.api import serializers +from core.tests.utils.urls import reload_urls + +pytestmark = pytest.mark.django_db + +# pylint: disable=unused-argument + + +def test_api_users_me_anonymous_public_standalone(): + """ + Anonymous users should not be allowed to retrieve their own user information from external + API if resource server is not enabled. + """ + reload_urls() + response = APIClient().get("/external_api/v1.0/users/me/") + + assert response.status_code == 404 + + +def test_api_users_me_connected_not_resource_server(): + """ + Connected users should not be allowed to retrieve their own user information from external + API if resource server is not enabled. + """ + reload_urls() + user = factories.UserFactory() + client = APIClient() + client.force_login(user) + + response = client.get("/external_api/v1.0/users/me/") + + assert response.status_code == 404 + + +def test_api_users_me_connected_resource_server( + user_token, resource_server_backend, user_specific_sub +): + """ + Connected users should be allowed to retrieve their own user information from external API + if resource server is enabled. + """ + client = APIClient() + client.credentials(HTTP_AUTHORIZATION=f"Bearer {user_token}") + + response = client.get("/external_api/v1.0/users/me/") + + assert response.status_code == 200 + data = response.json() + assert data["id"] == str(user_specific_sub.id) + assert data["email"] == user_specific_sub.email + + +def test_api_users_me_connected_resource_server_with_invalid_token( + user_token, resource_server_backend +): + """ + Connected users should not be allowed to retrieve their own user information from external API + if resource server is enabled with an invalid token. + """ + client = APIClient() + client.credentials(HTTP_AUTHORIZATION=f"Bearer {user_token}") + + response = client.get("/external_api/v1.0/users/me/") + + assert response.status_code == 401 + + +# Non allowed actions on resource server. + + +def test_api_users_list_resource_server_not_allowed( + user_token, resource_server_backend, user_specific_sub +): + """ + Connected users should notbe allowed to list users from a resource server. + """ + client = APIClient() + client.credentials(HTTP_AUTHORIZATION=f"Bearer {user_token}") + + response = client.get("/external_api/v1.0/users/") + + assert response.status_code == 403 + + +def test_api_users_retrieve_resource_server_not_allowed( + user_token, resource_server_backend, user_specific_sub +): + """ + Connected users should notbe allowed to list users from a resource server. + """ + client = APIClient() + client.credentials(HTTP_AUTHORIZATION=f"Bearer {user_token}") + + other_user = factories.UserFactory() + + response = client.get(f"/external_api/v1.0/users/{other_user.id!s}/") + + assert response.status_code == 403 + + +def test_api_users_put_patch_resource_server_not_allowed( + user_token, resource_server_backend, user_specific_sub +): + """ + Connected users should notbe allowed to list users from a resource server. + """ + client = APIClient() + client.credentials(HTTP_AUTHORIZATION=f"Bearer {user_token}") + + other_user = factories.UserFactory() + + new_user_values = serializers.UserSerializer(instance=factories.UserFactory()).data + response = client.put( + f"/external_api/v1.0/users/{other_user.id!s}/", new_user_values + ) + + assert response.status_code == 403 + + response = client.patch( + f"/external_api/v1.0/users/{other_user.id!s}/", + {"email": "new_email@example.com"}, + ) + + assert response.status_code == 403 + + +def test_api_users_delete_resource_server_not_allowed( + user_token, resource_server_backend, user_specific_sub +): + """ + Connected users should notbe allowed to list users from a resource server. + """ + client = APIClient() + client.credentials(HTTP_AUTHORIZATION=f"Bearer {user_token}") + + other_user = factories.UserFactory() + + response = client.delete(f"/external_api/v1.0/users/{other_user.id!s}/") + + assert response.status_code == 403 diff --git a/src/backend/core/tests/swagger/__init__.py b/src/backend/core/tests/swagger/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/core/tests/swagger/test_openapi_schema.py b/src/backend/core/tests/swagger/test_openapi_schema.py new file mode 100644 index 0000000..74b0f18 --- /dev/null +++ b/src/backend/core/tests/swagger/test_openapi_schema.py @@ -0,0 +1,42 @@ +""" +Test suite for generated openapi schema. +""" + +import json +from io import StringIO + +from django.core.management import call_command +from django.test import Client + +import pytest + +pytestmark = pytest.mark.django_db + + +def test_openapi_client_schema(): + """ + Generated and served OpenAPI client schema should be correct. + """ + # Start by generating the swagger.json file + output = StringIO() + call_command( + "spectacular", + "--api-version", + "v1.0", + "--urlconf", + "core.urls", + "--format", + "openapi-json", + "--file", + "core/tests/swagger/swagger.json", + stdout=output, + ) + assert output.getvalue() == "" + + response = Client().get("/api/v1.0/swagger.json") + + assert response.status_code == 200 + with open( + "core/tests/swagger/swagger.json", "r", encoding="utf-8" + ) as expected_schema: + assert response.json() == json.load(expected_schema) diff --git a/src/backend/core/tests/test_api_config.py b/src/backend/core/tests/test_api_config.py new file mode 100644 index 0000000..20fdcee --- /dev/null +++ b/src/backend/core/tests/test_api_config.py @@ -0,0 +1,161 @@ +""" +Test config API endpoints in the calendars core app. +""" + +import json + +from django.test import override_settings + +import pytest +from rest_framework.status import ( + HTTP_200_OK, +) +from rest_framework.test import APIClient + +from core import factories + +pytestmark = pytest.mark.django_db + + +@override_settings( + FRONTEND_THEME="test-theme", + FRONTEND_MORE_LINK="https://test.com", + FRONTEND_FEEDBACK_BUTTON_SHOW=True, + FRONTEND_FEEDBACK_BUTTON_IDLE=False, + FRONTEND_FEEDBACK_ITEMS={"form": {"url": "https://test.com"}}, + FRONTEND_FEEDBACK_MESSAGES_WIDGET_ENABLED=True, + FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL="https://test.com", + FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL="test", + FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH="https://test.com", + FRONTEND_HIDE_GAUFRE=True, + MEDIA_BASE_URL="http://testserver/", + SENTRY_DSN="https://sentry.test/123", + THEME_CUSTOMIZATION_FILE_PATH="", +) +@pytest.mark.parametrize("is_authenticated", [False, True]) +def test_api_config(is_authenticated): + """Anonymous users should be allowed to get the configuration.""" + client = APIClient() + + if is_authenticated: + user = factories.UserFactory() + client.force_login(user) + + response = client.get("/api/v1.0/config/") + assert response.status_code == HTTP_200_OK + assert response.json() == { + "ENVIRONMENT": "test", + "FRONTEND_THEME": "test-theme", + "FRONTEND_MORE_LINK": "https://test.com", + "FRONTEND_FEEDBACK_BUTTON_SHOW": True, + "FRONTEND_FEEDBACK_BUTTON_IDLE": False, + "FRONTEND_FEEDBACK_ITEMS": {"form": {"url": "https://test.com"}}, + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_ENABLED": True, + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL": "https://test.com", + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL": "test", + "FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH": "https://test.com", + "FRONTEND_HIDE_GAUFRE": True, + "LANGUAGES": [ + ["en-us", "English"], + ["fr-fr", "French"], + ["de-de", "German"], + ["nl-nl", "Dutch"], + ], + "LANGUAGE_CODE": "en-us", + "MEDIA_BASE_URL": "http://testserver/", + "SENTRY_DSN": "https://sentry.test/123", + "theme_customization": {}, + } + + +@override_settings( + THEME_CUSTOMIZATION_FILE_PATH="/not/existing/file.json", +) +@pytest.mark.parametrize("is_authenticated", [False, True]) +def test_api_config_with_invalid_theme_customization_file(is_authenticated): + """Anonymous users should be allowed to get the configuration.""" + client = APIClient() + + if is_authenticated: + user = factories.UserFactory() + client.force_login(user) + + response = client.get("/api/v1.0/config/") + assert response.status_code == HTTP_200_OK + content = response.json() + assert content["theme_customization"] == {} + + +@override_settings( + THEME_CUSTOMIZATION_FILE_PATH="/configuration/theme/invalid.json", +) +@pytest.mark.parametrize("is_authenticated", [False, True]) +def test_api_config_with_invalid_json_theme_customization_file(is_authenticated, fs): + """Anonymous users should be allowed to get the configuration.""" + fs.create_file( + "/configuration/theme/invalid.json", + contents="invalid json", + ) + client = APIClient() + + if is_authenticated: + user = factories.UserFactory() + client.force_login(user) + + response = client.get("/api/v1.0/config/") + assert response.status_code == HTTP_200_OK + content = response.json() + assert content["theme_customization"] == {} + + +@override_settings( + THEME_CUSTOMIZATION_FILE_PATH="/configuration/theme/default.json", +) +@pytest.mark.parametrize("is_authenticated", [False, True]) +def test_api_config_with_theme_customization(is_authenticated, fs): + """Anonymous users should be allowed to get the configuration.""" + fs.create_file( + "/configuration/theme/default.json", + contents=json.dumps( + { + "colors": { + "primary": "#000000", + "secondary": "#000000", + }, + } + ), + ) + client = APIClient() + + if is_authenticated: + user = factories.UserFactory() + client.force_login(user) + + response = client.get("/api/v1.0/config/") + assert response.status_code == HTTP_200_OK + content = response.json() + assert content["theme_customization"] == { + "colors": { + "primary": "#000000", + "secondary": "#000000", + }, + } + + +@pytest.mark.parametrize("is_authenticated", [False, True]) +def test_api_config_with_original_theme_customization(is_authenticated, settings): + """Anonymous users should be allowed to get the configuration.""" + client = APIClient() + + if is_authenticated: + user = factories.UserFactory() + client.force_login(user) + + response = client.get("/api/v1.0/config/") + assert response.status_code == HTTP_200_OK + content = response.json() + + with open(settings.THEME_CUSTOMIZATION_FILE_PATH, "r", encoding="utf-8") as f: + theme_customization = json.load(f) + + assert content["theme_customization"] == theme_customization diff --git a/src/backend/core/tests/test_api_users.py b/src/backend/core/tests/test_api_users.py new file mode 100644 index 0000000..bcd320e --- /dev/null +++ b/src/backend/core/tests/test_api_users.py @@ -0,0 +1,638 @@ +""" +Test users API endpoints in the calendars core app. +""" + +import pytest +from rest_framework.test import APIClient + +from core import factories, models +from core.api import serializers + +pytestmark = pytest.mark.django_db + + +def test_api_users_list_anonymous(): + """Anonymous users should not be allowed to list users.""" + factories.UserFactory() + client = APIClient() + response = client.get("/api/v1.0/users/") + assert response.status_code == 401 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "not_authenticated", + "detail": "Authentication credentials were not provided.", + }, + ], + "type": "client_error", + } + + +def test_api_users_list_authenticated(): + """ + Authenticated users should not be able to list users without a query. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + factories.UserFactory.create_batch(2) + response = client.get( + "/api/v1.0/users/", + ) + assert response.status_code == 200 + assert response.json() == [] + + +def test_api_users_list_query_inactive(): + """Inactive users should not be listed.""" + user = factories.UserFactory() + client = APIClient() + client.force_login(user) + + factories.UserFactory(email="john.doe@example.com", is_active=False) + lennon = factories.UserFactory(email="john.lennon@example.com") + + # Use email query to get exact match + response = client.get("/api/v1.0/users/?q=john.lennon@example.com") + + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [str(lennon.id)] + + # Inactive user should not be returned even with exact match + response = client.get("/api/v1.0/users/?q=john.doe@example.com") + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [] + + +def test_api_users_list_query_short_queries(): + """ + Queries shorter than 5 characters should return an empty result set. + """ + + user = factories.UserFactory() + client = APIClient() + client.force_login(user) + + factories.UserFactory(email="john.doe@example.com") + factories.UserFactory(email="john.lennon@example.com") + + response = client.get("/api/v1.0/users/?q=jo") + assert response.status_code == 200 + assert response.json() == [] + + response = client.get("/api/v1.0/users/?q=john") + assert response.status_code == 200 + assert response.json() == [] + + # Non-email queries (without @) return empty + response = client.get("/api/v1.0/users/?q=john.") + assert response.status_code == 200 + assert response.json() == [] + + +def test_api_users_list_limit(settings): + """ + Authenticated users should be able to list users and the number of results + should be limited to 10. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + # Use a base name with a length equal 5 to test that the limit is applied + base_name = "alice" + for i in range(15): + factories.UserFactory(email=f"{base_name}.{i}@example.com") + + # Non-email queries (without @) return empty + response = client.get( + "/api/v1.0/users/?q=alice", + ) + assert response.status_code == 200 + assert response.json() == [] + + # Email queries require exact match + settings.API_USERS_LIST_LIMIT = 100 + response = client.get( + "/api/v1.0/users/?q=alice.0@example.com", + ) + assert response.status_code == 200 + assert len(response.json()) == 1 + + +def test_api_users_list_throttling_authenticated(settings): + """ + Authenticated users should be throttled. + """ + user = factories.UserFactory() + client = APIClient() + client.force_login(user) + + settings.REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"]["user_list_burst"] = "3/minute" + + for _i in range(3): + response = client.get( + "/api/v1.0/users/?q=alice", + ) + assert response.status_code == 200 + + response = client.get( + "/api/v1.0/users/?q=alice", + ) + assert response.status_code == 429 + + +def test_api_users_list_query_email(): + """ + Authenticated users should be able to list users and filter by email. + Only exact email matches are returned (case-insensitive). + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + dave = factories.UserFactory(email="david.bowman@work.com") + factories.UserFactory(email="nicole.bowman@work.com") + + # Exact match works + response = client.get( + "/api/v1.0/users/?q=david.bowman@work.com", + ) + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [str(dave.id)] + + # Case-insensitive match works + response = client.get( + "/api/v1.0/users/?q=David.Bowman@Work.COM", + ) + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [str(dave.id)] + + # Typos don't match (exact match only) + response = client.get( + "/api/v1.0/users/?q=davig.bovman@worm.com", + ) + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [] + + response = client.get( + "/api/v1.0/users/?q=davig.bovman@worm.cop", + ) + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [] + + +def test_api_users_list_query_email_matching(): + """Email queries return exact matches only (case-insensitive).""" + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + user1 = factories.UserFactory(email="alice.johnson@example.gouv.fr") + user2 = factories.UserFactory(email="alice.johnnson@example.gouv.fr") + user3 = factories.UserFactory(email="alice.kohlson@example.gouv.fr") + user4 = factories.UserFactory(email="alicia.johnnson@example.gouv.fr") + user5 = factories.UserFactory(email="alicia.johnnson@example.gov.uk") + factories.UserFactory(email="alice.thomson@example.gouv.fr") + + # Exact match returns only that user + response = client.get( + "/api/v1.0/users/?q=alice.johnson@example.gouv.fr", + ) + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [str(user1.id)] + + # Different email returns different user + response = client.get("/api/v1.0/users/?q=alicia.johnnson@example.gouv.fr") + assert response.status_code == 200 + user_ids = [user["id"] for user in response.json()] + assert user_ids == [str(user4.id)] + + +def test_api_users_retrieve_me_anonymous(): + """Anonymous users should not be allowed to list users.""" + factories.UserFactory.create_batch(2) + client = APIClient() + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 401 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "not_authenticated", + "detail": "Authentication credentials were not provided.", + }, + ], + "type": "client_error", + } + + +def test_api_users_retrieve_me_authenticated(): + """Authenticated users should be able to retrieve their own user via the "/users/me" path.""" + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + factories.UserFactory.create_batch(2) + response = client.get( + "/api/v1.0/users/me/", + ) + + assert response.status_code == 200 + assert response.json() == { + "id": str(user.id), + "email": user.email, + "full_name": user.full_name, + "short_name": user.short_name, + "language": user.language, + } + + +def test_api_users_retrieve_anonymous(): + """Anonymous users should not be allowed to retrieve a user.""" + client = APIClient() + user = factories.UserFactory() + response = client.get(f"/api/v1.0/users/{user.id!s}/") + + assert response.status_code == 401 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "not_authenticated", + "detail": "Authentication credentials were not provided.", + }, + ], + "type": "client_error", + } + + +def test_api_users_retrieve_authenticated_self(): + """ + Authenticated users should be allowed to retrieve their own user. + The returned object should not contain the password. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + response = client.get( + f"/api/v1.0/users/{user.id!s}/", + ) + assert response.status_code == 405 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "method_not_allowed", + "detail": 'Method "GET" not allowed.', + }, + ], + "type": "client_error", + } + + +def test_api_users_retrieve_authenticated_other(): + """ + Authenticated users should be able to retrieve another user's detail view with + limited information. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + other_user = factories.UserFactory() + + response = client.get( + f"/api/v1.0/users/{other_user.id!s}/", + ) + assert response.status_code == 405 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "method_not_allowed", + "detail": 'Method "GET" not allowed.', + }, + ], + "type": "client_error", + } + + +def test_api_users_create_anonymous(): + """Anonymous users should not be able to create users via the API.""" + response = APIClient().post( + "/api/v1.0/users/", + { + "language": "fr-fr", + "password": "mypassword", + }, + ) + assert response.status_code == 401 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "not_authenticated", + "detail": "Authentication credentials were not provided.", + }, + ], + "type": "client_error", + } + + assert models.User.objects.exists() is False + + +def test_api_users_create_authenticated(): + """Authenticated users should not be able to create users via the API.""" + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + response = client.post( + "/api/v1.0/users/", + { + "language": "fr-fr", + "password": "mypassword", + }, + format="json", + ) + assert response.status_code == 405 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "method_not_allowed", + "detail": 'Method "POST" not allowed.', + }, + ], + "type": "client_error", + } + + assert models.User.objects.exclude(id=user.id).exists() is False + + +def test_api_users_update_anonymous(): + """Anonymous users should not be able to update users via the API.""" + user = factories.UserFactory() + + old_user_values = dict(serializers.UserSerializer(instance=user).data) + new_user_values = serializers.UserSerializer(instance=factories.UserFactory()).data + + response = APIClient().put( + f"/api/v1.0/users/{user.id!s}/", + new_user_values, + format="json", + ) + + assert response.status_code == 401 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "not_authenticated", + "detail": "Authentication credentials were not provided.", + }, + ], + "type": "client_error", + } + + user.refresh_from_db() + user_values = dict(serializers.UserSerializer(instance=user).data) + for key, value in user_values.items(): + assert value == old_user_values[key] + + +def test_api_users_update_authenticated_self(): + """ + Authenticated users should be able to update their own user but only "language" + and "timezone" fields. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + old_user_values = dict(serializers.UserSerializer(instance=user).data) + new_user_values = dict( + serializers.UserSerializer(instance=factories.UserFactory()).data + ) + + response = client.put( + f"/api/v1.0/users/{user.id!s}/", + new_user_values, + format="json", + ) + + assert response.status_code == 200 + user.refresh_from_db() + user_values = dict(serializers.UserSerializer(instance=user).data) + for key, value in user_values.items(): + if key in ["language", "timezone"]: + assert value == new_user_values[key] + else: + assert value == old_user_values[key] + + +def test_api_users_update_authenticated_other(): + """Authenticated users should not be allowed to update other users.""" + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + user = factories.UserFactory() + old_user_values = dict(serializers.UserSerializer(instance=user).data) + new_user_values = serializers.UserSerializer(instance=factories.UserFactory()).data + + response = client.put( + f"/api/v1.0/users/{user.id!s}/", + new_user_values, + format="json", + ) + + assert response.status_code == 403 + user.refresh_from_db() + user_values = dict(serializers.UserSerializer(instance=user).data) + for key, value in user_values.items(): + assert value == old_user_values[key] + + +def test_api_users_patch_anonymous(): + """Anonymous users should not be able to patch users via the API.""" + user = factories.UserFactory() + + old_user_values = dict(serializers.UserSerializer(instance=user).data) + new_user_values = dict( + serializers.UserSerializer(instance=factories.UserFactory()).data + ) + + for key, new_value in new_user_values.items(): + response = APIClient().patch( + f"/api/v1.0/users/{user.id!s}/", + {key: new_value}, + format="json", + ) + assert response.status_code == 401 + assert response.json() == { + "errors": [ + { + "attr": None, + "code": "not_authenticated", + "detail": "Authentication credentials were not provided.", + }, + ], + "type": "client_error", + } + + user.refresh_from_db() + user_values = dict(serializers.UserSerializer(instance=user).data) + for key, value in user_values.items(): + assert value == old_user_values[key] + + +def test_api_users_patch_authenticated_self(): + """ + Authenticated users should be able to patch their own user but only "language" + and "timezone" fields. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + old_user_values = dict(serializers.UserSerializer(instance=user).data) + new_user_values = dict( + serializers.UserSerializer(instance=factories.UserFactory()).data + ) + + for key, new_value in new_user_values.items(): + response = client.patch( + f"/api/v1.0/users/{user.id!s}/", + {key: new_value}, + format="json", + ) + assert response.status_code == 200 + + user.refresh_from_db() + user_values = dict(serializers.UserSerializer(instance=user).data) + for key, value in user_values.items(): + if key in ["language", "timezone"]: + assert value == new_user_values[key] + else: + assert value == old_user_values[key] + + +def test_api_users_patch_authenticated_other(): + """Authenticated users should not be allowed to patch other users.""" + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + user = factories.UserFactory() + old_user_values = dict(serializers.UserSerializer(instance=user).data) + new_user_values = dict( + serializers.UserSerializer(instance=factories.UserFactory()).data + ) + + for key, new_value in new_user_values.items(): + response = client.put( + f"/api/v1.0/users/{user.id!s}/", + {key: new_value}, + format="json", + ) + assert response.status_code == 403 + + user.refresh_from_db() + user_values = dict(serializers.UserSerializer(instance=user).data) + for key, value in user_values.items(): + assert value == old_user_values[key] + + +def test_api_users_delete_list_anonymous(): + """Anonymous users should not be allowed to delete a list of users.""" + factories.UserFactory.create_batch(2) + + client = APIClient() + response = client.delete("/api/v1.0/users/") + + assert response.status_code == 401 + assert models.User.objects.count() == 2 + + +def test_api_users_delete_list_authenticated(): + """Authenticated users should not be allowed to delete a list of users.""" + factories.UserFactory.create_batch(2) + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + response = client.delete( + "/api/v1.0/users/", + ) + + assert response.status_code == 405 + assert models.User.objects.count() == 3 + + +def test_api_users_delete_anonymous(): + """Anonymous users should not be allowed to delete a user.""" + user = factories.UserFactory() + + response = APIClient().delete(f"/api/v1.0/users/{user.id!s}/") + + assert response.status_code == 401 + assert models.User.objects.count() == 1 + + +def test_api_users_delete_authenticated(): + """ + Authenticated users should not be allowed to delete a user other than themselves. + """ + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + other_user = factories.UserFactory() + + response = client.delete( + f"/api/v1.0/users/{other_user.id!s}/", + ) + + assert response.status_code == 405 + assert models.User.objects.count() == 2 + + +def test_api_users_delete_self(): + """Authenticated users should not be able to delete their own user.""" + user = factories.UserFactory() + + client = APIClient() + client.force_login(user) + + response = client.delete( + f"/api/v1.0/users/{user.id!s}/", + ) + + assert response.status_code == 405 + assert models.User.objects.count() == 1 diff --git a/src/backend/core/tests/test_caldav_service.py b/src/backend/core/tests/test_caldav_service.py new file mode 100644 index 0000000..3baa426 --- /dev/null +++ b/src/backend/core/tests/test_caldav_service.py @@ -0,0 +1,71 @@ +"""Tests for CalDAV service integration with DAViCal.""" + +from unittest.mock import Mock, patch + +from django.conf import settings + +import pytest + +from core import factories +from core.services.caldav_service import CalendarService, DAViCalClient + + +@pytest.mark.django_db +class TestDAViCalClient: + """Tests for DAViCalClient authentication and communication.""" + + def test_get_client_sends_x_forwarded_user_header(self): + """Test that DAVClient is configured with X-Forwarded-User header.""" + user = factories.UserFactory(email="test@example.com") + client = DAViCalClient() + + dav_client = client._get_client(user) + + # Verify the client is configured correctly + assert dav_client.username == user.email + # Password should be empty (None or empty string) for external auth + assert not dav_client.password or dav_client.password == "" + + # Verify the X-Forwarded-User header is set + # The caldav library stores headers as a CaseInsensitiveDict + assert hasattr(dav_client, "headers") + assert "X-Forwarded-User" in dav_client.headers + assert dav_client.headers["X-Forwarded-User"] == user.email + + @pytest.mark.skipif( + not getattr(settings, "DAVICAL_URL", None), + reason="DAViCal URL not configured", + ) + def test_create_calendar_authenticates_with_davical(self): + """Test that calendar creation authenticates successfully with DAViCal.""" + user = factories.UserFactory(email="test@example.com") + client = DAViCalClient() + + # Ensure user exists in DAViCal + client.ensure_user_exists(user) + + # Try to create a calendar - this should authenticate successfully + calendar_path = client.create_calendar( + user, calendar_name="Test Calendar", calendar_id="test-calendar-id" + ) + + # Verify calendar path was returned + assert calendar_path is not None + assert calendar_path.startswith("/caldav.php/") + assert user.email in calendar_path + + def test_calendar_service_creates_calendar(self): + """Test that CalendarService can create a calendar through DAViCal.""" + user = factories.UserFactory(email="test@example.com") + service = CalendarService() + + # Create a calendar + calendar = service.create_calendar(user, name="My Calendar", color="#ff0000") + + # Verify calendar was created + assert calendar is not None + assert calendar.owner == user + assert calendar.name == "My Calendar" + assert calendar.color == "#ff0000" + assert calendar.davical_path is not None + assert calendar.davical_path.startswith("/caldav.php/") diff --git a/src/backend/core/tests/test_models_users.py b/src/backend/core/tests/test_models_users.py new file mode 100644 index 0000000..1bba4e2 --- /dev/null +++ b/src/backend/core/tests/test_models_users.py @@ -0,0 +1,46 @@ +""" +Unit tests for the User model +""" + +from unittest import mock + +from django.core.exceptions import ValidationError + +import pytest + +from core import factories, models + +pytestmark = pytest.mark.django_db + + +def test_models_users_str(): + """The str representation should be the email.""" + user = factories.UserFactory() + assert str(user) == user.email + + +def test_models_users_id_unique(): + """The "id" field should be unique.""" + user = factories.UserFactory() + with pytest.raises(ValidationError, match="User with this Id already exists."): + factories.UserFactory(id=user.id) + + +def test_models_users_send_mail_main_existing(): + """The "email_user' method should send mail to the user's email address.""" + user = factories.UserFactory() + + with mock.patch("django.core.mail.send_mail") as mock_send: + user.email_user("my subject", "my message") + + mock_send.assert_called_once_with("my subject", "my message", None, [user.email]) + + +def test_models_users_send_mail_main_missing(): + """The "email_user' method should fail if the user has no email address.""" + user = factories.UserFactory(email=None) + + with pytest.raises(ValueError) as excinfo: + user.email_user("my subject", "my message") + + assert str(excinfo.value) == "User has no email address." diff --git a/src/backend/core/tests/test_settings.py b/src/backend/core/tests/test_settings.py new file mode 100644 index 0000000..a3af681 --- /dev/null +++ b/src/backend/core/tests/test_settings.py @@ -0,0 +1,30 @@ +""" +Unit tests for the User model +""" + +import pytest + +from calendars.settings import Base + + +def test_invalid_settings_oidc_email_configuration(): + """ + The OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION and OIDC_ALLOW_DUPLICATE_EMAILS settings + should not be both set to True simultaneously. + """ + + class TestSettings(Base): + """Fake test settings.""" + + OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION = True + OIDC_ALLOW_DUPLICATE_EMAILS = True + + # The validation is performed during post_setup + with pytest.raises(ValueError) as excinfo: + TestSettings().post_setup() + + # Check the exception message + assert str(excinfo.value) == ( + "Both OIDC_FALLBACK_TO_EMAIL_FOR_IDENTIFICATION and " + "OIDC_ALLOW_DUPLICATE_EMAILS cannot be set to True simultaneously. " + ) diff --git a/src/backend/core/tests/utils/urls.py b/src/backend/core/tests/utils/urls.py new file mode 100644 index 0000000..16f6d1f --- /dev/null +++ b/src/backend/core/tests/utils/urls.py @@ -0,0 +1,20 @@ +"""Utils for testing URLs.""" + +import importlib + +from django.urls import clear_url_caches + + +def reload_urls(): + """ + Reload the URLs. Since the url are loaded based on a + settings value, we need to reload the urls to make the + URL settings based condition effective. + """ + import core.urls # pylint:disable=import-outside-toplevel # noqa: PLC0415 + + import calendars.urls # pylint:disable=import-outside-toplevel # noqa: PLC0415 + + importlib.reload(core.urls) + importlib.reload(calendars.urls) + clear_url_caches() diff --git a/src/backend/core/urls.py b/src/backend/core/urls.py new file mode 100644 index 0000000..9d17eed --- /dev/null +++ b/src/backend/core/urls.py @@ -0,0 +1,61 @@ +"""URL configuration for the core app.""" + +from django.conf import settings +from django.urls import include, path, re_path + +from lasuite.oidc_login.urls import urlpatterns as oidc_urls +from rest_framework.routers import DefaultRouter + +from core.api import viewsets +from core.api.viewsets_caldav import CalDAVProxyView +from core.external_api import viewsets as external_api_viewsets + +# - Main endpoints +router = DefaultRouter() +router.register("users", viewsets.UserViewSet, basename="users") +router.register("calendars", viewsets.CalendarViewSet, basename="calendars") + +urlpatterns = [ + path( + f"api/{settings.API_VERSION}/", + include( + [ + *router.urls, + *oidc_urls, + # CalDAV proxy - root path (must come before catch-all to match /caldav exactly) + path("caldav", CalDAVProxyView.as_view(), name="caldav-root"), + path("caldav/", CalDAVProxyView.as_view(), name="caldav-root-slash"), + # CalDAV proxy - catch all paths with content + re_path( + r"^caldav/(?P.+)$", + CalDAVProxyView.as_view(), + name="caldav-proxy", + ), + ] + ), + ), + path(f"api/{settings.API_VERSION}/config/", viewsets.ConfigView.as_view()), +] + + +if settings.OIDC_RESOURCE_SERVER_ENABLED: + # - Resource server routes + external_api_router = DefaultRouter() + + users_access_config = settings.EXTERNAL_API.get("users", {}) + if users_access_config.get("enabled", False): + external_api_router.register( + "users", + external_api_viewsets.ResourceServerUserViewSet, + basename="resource_server_users", + ) + + external_api_urls = [*external_api_router.urls] + + if external_api_urls: + urlpatterns.append( + path( + f"external_api/{settings.API_VERSION}/", + include(external_api_urls), + ) + ) diff --git a/src/backend/e2e/__init__.py b/src/backend/e2e/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/e2e/management/commands/__init__.py b/src/backend/e2e/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/e2e/serializers.py b/src/backend/e2e/serializers.py new file mode 100644 index 0000000..62ce878 --- /dev/null +++ b/src/backend/e2e/serializers.py @@ -0,0 +1,12 @@ +"""Serializers for E2E tests.""" + +from rest_framework import serializers + + +# Suppress the warning about not implementing `create` and `update` methods +# since we don't use a model and only rely on the serializer for validation +# pylint: disable=abstract-method +class E2EAuthSerializer(serializers.Serializer): + """Serializer for E2E authentication.""" + + email = serializers.EmailField(required=True) diff --git a/src/backend/e2e/tests/test_api_e2e.py b/src/backend/e2e/tests/test_api_e2e.py new file mode 100644 index 0000000..58123a4 --- /dev/null +++ b/src/backend/e2e/tests/test_api_e2e.py @@ -0,0 +1,83 @@ +""" +Test e2e API endpoints. +""" + +from django.test.utils import override_settings + +import pytest +from rest_framework.test import APIClient + +from core.tests.utils.urls import reload_urls + +pytestmark = pytest.mark.django_db + + +def test_api_e2e_user_auth_no_urls(): + """E2E URLs not enabled should 404.""" + client = APIClient() + + response = client.post("/api/v1.0/e2e/user-auth/", {"email": "test@example.com"}) + assert response.status_code == 404 + + +@override_settings(LOAD_E2E_URLS=True) +def test_api_e2e_user_auth_anonymous(): + """Anonymous users should be allowed to create and login a user.""" + reload_urls() + client = APIClient() + + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 401 + + response = client.post("/api/v1.0/e2e/user-auth/", {"email": "test@example.com"}) + assert response.status_code == 200 + assert response.json() == {"email": "test@example.com"} + + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 200 + assert response.json()["email"] == "test@example.com" + + +@override_settings(LOAD_E2E_URLS=True) +def test_api_e2e_user_auth_authenticated(): + """Authenticated users should be allowed to create and login a new user.""" + reload_urls() + client = APIClient() + + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 401 + + response = client.post("/api/v1.0/e2e/user-auth/", {"email": "test@example.com"}) + assert response.status_code == 200 + assert response.json() == {"email": "test@example.com"} + + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 200 + assert response.json()["email"] == "test@example.com" + + response = client.post("/api/v1.0/e2e/user-auth/", {"email": "test2@example.com"}) + assert response.status_code == 200 + assert response.json() == {"email": "test2@example.com"} + + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 200 + assert response.json()["email"] == "test2@example.com" + + +@override_settings(LOAD_E2E_URLS=True) +def test_api_e2e_user_auth_email_required(): + """Email is required.""" + reload_urls() + client = APIClient() + + response = client.get("/api/v1.0/users/me/") + assert response.status_code == 401 + + response = client.post("/api/v1.0/e2e/user-auth/", {}) + assert response.status_code == 400 + assert response.json() == { + "type": "validation_error", + "errors": [ + {"code": "required", "detail": "This field is required.", "attr": "email"} + ], + } diff --git a/src/backend/e2e/urls.py b/src/backend/e2e/urls.py new file mode 100644 index 0000000..997a51e --- /dev/null +++ b/src/backend/e2e/urls.py @@ -0,0 +1,26 @@ +"""URL configuration for the e2e app.""" + +from django.conf import settings +from django.urls import include, path + +from rest_framework.routers import DefaultRouter + +from e2e import viewsets + +user_auth_router = DefaultRouter() +user_auth_router.register( + "user-auth", + viewsets.UserAuthViewSet, + basename="user-auth", +) + +urlpatterns = [ + path( + f"api/{settings.API_VERSION}/e2e/", + include( + [ + *user_auth_router.urls, + ] + ), + ), +] diff --git a/src/backend/e2e/utils.py b/src/backend/e2e/utils.py new file mode 100644 index 0000000..60d3c40 --- /dev/null +++ b/src/backend/e2e/utils.py @@ -0,0 +1,11 @@ +"""E2E utils.""" + +from core import factories, models + + +def get_or_create_e2e_user(email): + """Get or create an E2E user.""" + user = models.User.objects.filter(email=email).first() + if not user: + user = factories.UserFactory(email=email, sub=None, language="en-us") + return user diff --git a/src/backend/e2e/viewsets.py b/src/backend/e2e/viewsets.py new file mode 100644 index 0000000..6150242 --- /dev/null +++ b/src/backend/e2e/viewsets.py @@ -0,0 +1,40 @@ +"""Viewsets for the e2e app.""" + +from django.contrib.auth import login + +import rest_framework as drf +from rest_framework import response as drf_response +from rest_framework import status +from rest_framework.permissions import AllowAny + +from core import models + +from e2e.serializers import E2EAuthSerializer + + +class UserAuthViewSet(drf.viewsets.ViewSet): + """Viewset to handle user authentication""" + + permission_classes = [AllowAny] + authentication_classes = [] + + def create(self, request): + """ + POST /api/v1.0/e2e/user-auth/ + Create a user with the given email if it doesn't exist and log them in + """ + serializer = E2EAuthSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + + # Create user if doesn't exist + user = models.User.objects.filter( + email=serializer.validated_data["email"] + ).first() + if not user: + user = models.User(email=serializer.validated_data["email"]) + user.set_unusable_password() + user.save() + + login(request, user, "django.contrib.auth.backends.ModelBackend") + + return drf_response.Response({"email": user.email}, status=status.HTTP_200_OK) diff --git a/src/backend/entrypoint b/src/backend/entrypoint new file mode 100755 index 0000000..5ff4aa1 --- /dev/null +++ b/src/backend/entrypoint @@ -0,0 +1,35 @@ +#!/bin/sh +# +# The container user (see USER in the Dockerfile) is an un-privileged user that +# does not exists and is not created during the build phase (see Dockerfile). +# Hence, we use this entrypoint to wrap commands that will be run in the +# container to create an entry for this user in the /etc/passwd file. +# +# The following environment variables may be passed to the container to +# customize running user account: +# +# * USER_NAME: container user name (default: default) +# * HOME : container user home directory (default: none) +# +# To pass environment variables, you can either use the -e option of the docker run command: +# +# docker run --rm -e USER_NAME=foo -e HOME='/home/foo' calendars-backend:latest python manage.py migrate +# +# or define new variables in an environment file to use with docker or docker compose: +# +# # env.d/production +# USER_NAME=foo +# HOME=/home/foo +# +# docker run --rm --env-file env.d/production calendars-backend:latest python manage.py migrate +# + +echo "🐳(entrypoint) creating user running in the container..." +if ! whoami > /dev/null 2>&1; then + if [ -w /etc/passwd ]; then + echo "${USER_NAME:-default}:x:$(id -u):$(id -g):${USER_NAME:-default} user:${HOME}:/sbin/nologin" >> /etc/passwd + fi +fi + +echo "🐳(entrypoint) running your command: ${*}" +exec "$@" diff --git a/src/backend/gunicorn.conf.py b/src/backend/gunicorn.conf.py new file mode 100644 index 0000000..dd33428 --- /dev/null +++ b/src/backend/gunicorn.conf.py @@ -0,0 +1,16 @@ +# Gunicorn-django settings +bind = ["0.0.0.0:8000"] +name = "calendars" +python_path = "/app" + +# Run +graceful_timeout = 90 +timeout = 90 +workers = 3 + +# Logging +# Using '-' for the access log file makes gunicorn log accesses to stdout +accesslog = "-" +# Using '-' for the error log file makes gunicorn log errors to stderr +errorlog = "-" +loglevel = "info" diff --git a/src/backend/locale/de_DE/LC_MESSAGES/django.po b/src/backend/locale/de_DE/LC_MESSAGES/django.po new file mode 100644 index 0000000..2308ef9 --- /dev/null +++ b/src/backend/locale/de_DE/LC_MESSAGES/django.po @@ -0,0 +1,455 @@ +msgid "" +msgstr "" +"Project-Id-Version: lasuite-docs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-05-19 15:10+0000\n" +"PO-Revision-Date: 2025-01-27 09:27\n" +"Last-Translator: \n" +"Language-Team: German\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: lasuite-docs\n" +"X-Crowdin-Project-ID: 754523\n" +"X-Crowdin-Language: de\n" +"X-Crowdin-File: backend-calendars.pot\n" +"X-Crowdin-File-ID: 18\n" + +#: core/admin.py:26 +msgid "Personal info" +msgstr "Persönliche Daten" + +#: core/admin.py:39 core/admin.py:119 +msgid "Permissions" +msgstr "Berechtigungen" + +#: core/admin.py:51 +msgid "Important dates" +msgstr "Wichtige Daten" + +#: core/admin.py:129 +msgid "Tree structure" +msgstr "" + +#: core/api/filters.py:16 +msgid "Title" +msgstr "Titel" + +#: core/api/filters.py:28 +msgid "Creator is me" +msgstr "Ersteller bin ich" + +#: core/api/filters.py:31 +msgid "Favorite" +msgstr "Favorit" + +#: core/api/serializers.py:304 +msgid "An item with this title already exists in the current path." +msgstr "" + +#: core/api/serializers.py:397 +msgid "This field is required for files." +msgstr "" + +#: core/api/serializers.py:409 +msgid "This field is required for folders." +msgstr "" + +#: core/models.py:53 core/models.py:60 +msgid "Reader" +msgstr "Lesen" + +#: core/models.py:54 core/models.py:61 +msgid "Editor" +msgstr "Bearbeiten" + +#: core/models.py:62 +msgid "Administrator" +msgstr "" + +#: core/models.py:63 +msgid "Owner" +msgstr "Besitzer" + +#: core/models.py:74 +msgid "Restricted" +msgstr "Beschränkt" + +#: core/models.py:78 +msgid "Authenticated" +msgstr "Authentifiziert" + +#: core/models.py:80 +msgid "Public" +msgstr "Öffentlich" + +#: core/models.py:86 +msgid "Folder" +msgstr "" + +#: core/models.py:87 +msgid "File" +msgstr "" + +#: core/models.py:93 +msgid "Pending" +msgstr "" + +#: core/models.py:94 +msgid "Uploaded" +msgstr "" + +#: core/models.py:116 +msgid "id" +msgstr "" + +#: core/models.py:117 +msgid "primary key for the record as UUID" +msgstr "" + +#: core/models.py:123 +msgid "created on" +msgstr "Erstellt" + +#: core/models.py:124 +msgid "date and time at which a record was created" +msgstr "Datum und Uhrzeit, an dem ein Datensatz erstellt wurde" + +#: core/models.py:129 +msgid "updated on" +msgstr "Aktualisiert" + +#: core/models.py:130 +msgid "date and time at which a record was last updated" +msgstr "Datum und Uhrzeit, an dem zuletzt aktualisiert wurde" + +#: core/models.py:166 +msgid "" +"We couldn't find a user with this sub but the email is already associated " +"with a registered user." +msgstr "" + +#: core/models.py:179 +msgid "" +"Enter a valid sub. This value may contain only letters, numbers, and @/./+/-/" +"_/: characters." +msgstr "" +"Geben Sie eine gültige Unterseite ein. Dieser Wert darf nur Buchstaben, " +"Zahlen und die @/./+/-/_/: Zeichen enthalten." + +#: core/models.py:185 +msgid "sub" +msgstr "unter" + +#: core/models.py:187 +msgid "" +"Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: " +"characters only." +msgstr "" +"Erforderlich. 255 Zeichen oder weniger. Buchstaben, Zahlen und die Zeichen " +"@/./+/-/_/:" + +#: core/models.py:196 +msgid "full name" +msgstr "Name" + +#: core/models.py:197 +msgid "short name" +msgstr "Kurzbezeichnung" + +#: core/models.py:199 +msgid "identity email address" +msgstr "Identitäts-E-Mail-Adresse" + +#: core/models.py:204 +msgid "admin email address" +msgstr "Admin E-Mail-Adresse" + +#: core/models.py:211 +msgid "language" +msgstr "Sprache" + +#: core/models.py:212 +msgid "The language in which the user wants to see the interface." +msgstr "Die Sprache, in der der Benutzer die Benutzeroberfläche sehen möchte." + +#: core/models.py:218 +msgid "The timezone in which the user wants to see times." +msgstr "Die Zeitzone, in der der Nutzer Zeiten sehen möchte." + +#: core/models.py:221 +msgid "device" +msgstr "Gerät" + +#: core/models.py:223 +msgid "Whether the user is a device or a real user." +msgstr "Ob der Benutzer ein Gerät oder ein echter Benutzer ist." + +#: core/models.py:226 +msgid "staff status" +msgstr "Status des Teammitgliedes" + +#: core/models.py:228 +msgid "Whether the user can log into this admin site." +msgstr "Gibt an, ob der Benutzer sich in diese Admin-Seite einloggen kann." + +#: core/models.py:231 +msgid "active" +msgstr "aktiviert" + +#: core/models.py:234 +msgid "" +"Whether this user should be treated as active. Unselect this instead of " +"deleting accounts." +msgstr "" +"Ob dieser Benutzer als aktiviert behandelt werden soll. Deaktivieren Sie " +"diese Option, anstatt Konten zu löschen." + +#: core/models.py:246 +msgid "user" +msgstr "Benutzer" + +#: core/models.py:247 +msgid "users" +msgstr "Benutzer" + +#: core/models.py:269 +msgid "Workspace" +msgstr "" + +#: core/models.py:457 +msgid "Only folders can have children." +msgstr "" + +#: core/models.py:470 +#, fuzzy +#| msgid "This team is already in this item." +msgid "title already exists in this folder." +msgstr "Dieses Team befindet sich bereits in diesem Dokument." + +#: core/models.py:504 +msgid "title" +msgstr "Titel" + +#: core/models.py:549 +msgid "Item" +msgstr "" + +#: core/models.py:550 +#, fuzzy +#| msgid "items" +msgid "Items" +msgstr "Dokumente" + +#: core/models.py:815 +#, fuzzy, python-brace-format +#| msgid "{name} shared a item with you!" +msgid "{name} shared an item with you!" +msgstr "{name} hat ein Dokument mit Ihnen geteilt!" + +#: core/models.py:817 +#, python-brace-format +msgid "{name} invited you with the role \"{role}\" on the following item:" +msgstr "" +"{name} hat Sie mit der Rolle \"{role}\" zu folgendem Dokument eingeladen:" + +#: core/models.py:820 +#, fuzzy, python-brace-format +#| msgid "{name} shared a item with you: {title}" +msgid "{name} shared an item with you: {title}" +msgstr "{name} hat ein Dokument mit Ihnen geteilt: {title}" + +#: core/models.py:872 +#, fuzzy +#| msgid "This team is already in this template." +msgid "This item is already hard deleted." +msgstr "Dieses Team ist bereits in diesem Template." + +#: core/models.py:882 +msgid "To hard delete an item, it must first be soft deleted." +msgstr "" + +#: core/models.py:902 +#, fuzzy +#| msgid "This team is already in this template." +msgid "This item is not deleted." +msgstr "Dieses Team ist bereits in diesem Template." + +#: core/models.py:918 +msgid "This item was permanently deleted and cannot be restored." +msgstr "" + +#: core/models.py:968 +msgid "Only folders can be targeted when moving an item" +msgstr "" + +#: core/models.py:1021 +#, fuzzy +#| msgid "item/user link trace" +msgid "Item/user link trace" +msgstr "Dokument/Benutzer Linkverfolgung" + +#: core/models.py:1022 +#, fuzzy +#| msgid "item/user link traces" +msgid "Item/user link traces" +msgstr "Dokument/Benutzer Linkverfolgung" + +#: core/models.py:1028 +msgid "A link trace already exists for this item/user." +msgstr "" + +#: core/models.py:1051 +#, fuzzy +#| msgid "item favorite" +msgid "Item favorite" +msgstr "Dokumentenfavorit" + +#: core/models.py:1052 +#, fuzzy +#| msgid "item favorites" +msgid "Item favorites" +msgstr "Dokumentfavoriten" + +#: core/models.py:1058 +msgid "" +"This item is already targeted by a favorite relation instance for the same " +"user." +msgstr "" +"Dieses Dokument ist bereits durch den gleichen Benutzer favorisiert worden." + +#: core/models.py:1080 +#, fuzzy +#| msgid "item/user relation" +msgid "Item/user relation" +msgstr "Dokument/Benutzerbeziehung" + +#: core/models.py:1081 +#, fuzzy +#| msgid "item/user relations" +msgid "Item/user relations" +msgstr "Dokument/Benutzerbeziehungen" + +#: core/models.py:1087 +msgid "This user is already in this item." +msgstr "Dieser Benutzer befindet sich bereits in diesem Dokument." + +#: core/models.py:1093 +msgid "This team is already in this item." +msgstr "Dieses Team befindet sich bereits in diesem Dokument." + +#: core/models.py:1099 +msgid "Either user or team must be set, not both." +msgstr "Benutzer oder Team müssen gesetzt werden, nicht beides." + +#: core/models.py:1126 +msgid "email address" +msgstr "E-Mail-Adresse" + +#: core/models.py:1145 +#, fuzzy +#| msgid "item invitation" +msgid "Item invitation" +msgstr "Einladung zum Dokument" + +#: core/models.py:1146 +#, fuzzy +#| msgid "item invitations" +msgid "Item invitations" +msgstr "Dokumenteinladungen" + +#: core/templates/mail/html/invitation.html:162 +#: core/templates/mail/text/invitation.txt:3 +msgid "Logo email" +msgstr "" + +#: core/templates/mail/html/invitation.html:209 +#: core/templates/mail/text/invitation.txt:10 +msgid "Open" +msgstr "" + +#: core/templates/mail/html/invitation.html:226 +#: core/templates/mail/text/invitation.txt:14 +msgid "" +" Calendars, your new essential tool for organizing, sharing and collaborating as " +"a team. " +msgstr "" + +#: core/templates/mail/html/invitation.html:233 +#: core/templates/mail/text/invitation.txt:16 +#, python-format +msgid " Brought to you by %(brandname)s " +msgstr "" + +#: calendars/settings.py:250 +msgid "English" +msgstr "Englisch" + +#: calendars/settings.py:251 +msgid "French" +msgstr "Französisch" + +#: calendars/settings.py:252 +msgid "German" +msgstr "Deutsch" + +#~ msgid "Invalid response format or token verification failed" +#~ msgstr "Ungültiges Antwortformat oder Token-Verifizierung fehlgeschlagen" + +#~ msgid "User account is disabled" +#~ msgstr "Benutzerkonto ist deaktiviert" + +#, fuzzy +#~| msgid "Untitled item" +#~ msgid "Untitled Item" +#~ msgstr "Unbenanntes Dokument" + +#~ msgid "This email is already associated to a registered user." +#~ msgstr "Diese E-Mail ist bereits einem registrierten Benutzer zugeordnet." + +#~ msgid "A new item was created on your behalf!" +#~ msgstr "Ein neues Dokument wurde in Ihrem Namen erstellt!" + +#~ msgid "You have been granted ownership of a new item:" +#~ msgstr "Sie sind Besitzer eines neuen Dokuments:" + +#~ msgid "Body" +#~ msgstr "Inhalt" + +#~ msgid "Body type" +#~ msgstr "Typ" + +#~ msgid "item" +#~ msgstr "Dokument" + +#~ msgid "description" +#~ msgstr "Beschreibung" + +#~ msgid "code" +#~ msgstr "Code" + +#~ msgid "css" +#~ msgstr "CSS" + +#~ msgid "public" +#~ msgstr "öffentlich" + +#~ msgid "Whether this template is public for anyone to use." +#~ msgstr "Ob diese Vorlage für jedermann öffentlich ist." + +#~ msgid "Template" +#~ msgstr "Vorlage" + +#~ msgid "Templates" +#~ msgstr "Vorlagen" + +#~ msgid "Template/user relation" +#~ msgstr "Vorlage/Benutzer-Beziehung" + +#~ msgid "Template/user relations" +#~ msgstr "Vorlage/Benutzerbeziehungen" + +#~ msgid "This user is already in this template." +#~ msgstr "Dieser Benutzer ist bereits in dieser Vorlage." diff --git a/src/backend/locale/en_US/LC_MESSAGES/django.po b/src/backend/locale/en_US/LC_MESSAGES/django.po new file mode 100644 index 0000000..e4d70c6 --- /dev/null +++ b/src/backend/locale/en_US/LC_MESSAGES/django.po @@ -0,0 +1,362 @@ +msgid "" +msgstr "" +"Project-Id-Version: lasuite-docs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-05-19 15:10+0000\n" +"PO-Revision-Date: 2025-01-27 09:27\n" +"Last-Translator: \n" +"Language-Team: English\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: lasuite-docs\n" +"X-Crowdin-Project-ID: 754523\n" +"X-Crowdin-Language: en\n" +"X-Crowdin-File: backend-calendars.pot\n" +"X-Crowdin-File-ID: 18\n" + +#: core/admin.py:26 +msgid "Personal info" +msgstr "" + +#: core/admin.py:39 core/admin.py:119 +msgid "Permissions" +msgstr "" + +#: core/admin.py:51 +msgid "Important dates" +msgstr "" + +#: core/admin.py:129 +msgid "Tree structure" +msgstr "" + +#: core/api/filters.py:16 +msgid "Title" +msgstr "" + +#: core/api/filters.py:28 +msgid "Creator is me" +msgstr "" + +#: core/api/filters.py:31 +msgid "Favorite" +msgstr "" + +#: core/api/serializers.py:304 +msgid "An item with this title already exists in the current path." +msgstr "" + +#: core/api/serializers.py:397 +msgid "This field is required for files." +msgstr "" + +#: core/api/serializers.py:409 +msgid "This field is required for folders." +msgstr "" + +#: core/models.py:53 core/models.py:60 +msgid "Reader" +msgstr "" + +#: core/models.py:54 core/models.py:61 +msgid "Editor" +msgstr "" + +#: core/models.py:62 +msgid "Administrator" +msgstr "" + +#: core/models.py:63 +msgid "Owner" +msgstr "" + +#: core/models.py:74 +msgid "Restricted" +msgstr "" + +#: core/models.py:78 +msgid "Authenticated" +msgstr "" + +#: core/models.py:80 +msgid "Public" +msgstr "" + +#: core/models.py:86 +msgid "Folder" +msgstr "" + +#: core/models.py:87 +msgid "File" +msgstr "" + +#: core/models.py:93 +msgid "Pending" +msgstr "" + +#: core/models.py:94 +msgid "Uploaded" +msgstr "" + +#: core/models.py:116 +msgid "id" +msgstr "" + +#: core/models.py:117 +msgid "primary key for the record as UUID" +msgstr "" + +#: core/models.py:123 +msgid "created on" +msgstr "" + +#: core/models.py:124 +msgid "date and time at which a record was created" +msgstr "" + +#: core/models.py:129 +msgid "updated on" +msgstr "" + +#: core/models.py:130 +msgid "date and time at which a record was last updated" +msgstr "" + +#: core/models.py:166 +msgid "" +"We couldn't find a user with this sub but the email is already associated " +"with a registered user." +msgstr "" + +#: core/models.py:179 +msgid "" +"Enter a valid sub. This value may contain only letters, numbers, and @/./+/-/" +"_/: characters." +msgstr "" + +#: core/models.py:185 +msgid "sub" +msgstr "" + +#: core/models.py:187 +msgid "" +"Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: " +"characters only." +msgstr "" + +#: core/models.py:196 +msgid "full name" +msgstr "" + +#: core/models.py:197 +msgid "short name" +msgstr "" + +#: core/models.py:199 +msgid "identity email address" +msgstr "" + +#: core/models.py:204 +msgid "admin email address" +msgstr "" + +#: core/models.py:211 +msgid "language" +msgstr "" + +#: core/models.py:212 +msgid "The language in which the user wants to see the interface." +msgstr "" + +#: core/models.py:218 +msgid "The timezone in which the user wants to see times." +msgstr "" + +#: core/models.py:221 +msgid "device" +msgstr "" + +#: core/models.py:223 +msgid "Whether the user is a device or a real user." +msgstr "" + +#: core/models.py:226 +msgid "staff status" +msgstr "" + +#: core/models.py:228 +msgid "Whether the user can log into this admin site." +msgstr "" + +#: core/models.py:231 +msgid "active" +msgstr "" + +#: core/models.py:234 +msgid "" +"Whether this user should be treated as active. Unselect this instead of " +"deleting accounts." +msgstr "" + +#: core/models.py:246 +msgid "user" +msgstr "" + +#: core/models.py:247 +msgid "users" +msgstr "" + +#: core/models.py:269 +msgid "Workspace" +msgstr "" + +#: core/models.py:457 +msgid "Only folders can have children." +msgstr "" + +#: core/models.py:470 +msgid "title already exists in this folder." +msgstr "" + +#: core/models.py:504 +msgid "title" +msgstr "" + +#: core/models.py:549 +msgid "Item" +msgstr "" + +#: core/models.py:550 +msgid "Items" +msgstr "" + +#: core/models.py:815 +#, python-brace-format +msgid "{name} shared an item with you!" +msgstr "" + +#: core/models.py:817 +#, python-brace-format +msgid "{name} invited you with the role \"{role}\" on the following item:" +msgstr "" + +#: core/models.py:820 +#, python-brace-format +msgid "{name} shared an item with you: {title}" +msgstr "" + +#: core/models.py:872 +msgid "This item is already hard deleted." +msgstr "" + +#: core/models.py:882 +msgid "To hard delete an item, it must first be soft deleted." +msgstr "" + +#: core/models.py:902 +msgid "This item is not deleted." +msgstr "" + +#: core/models.py:918 +msgid "This item was permanently deleted and cannot be restored." +msgstr "" + +#: core/models.py:968 +msgid "Only folders can be targeted when moving an item" +msgstr "" + +#: core/models.py:1021 +msgid "Item/user link trace" +msgstr "" + +#: core/models.py:1022 +msgid "Item/user link traces" +msgstr "" + +#: core/models.py:1028 +msgid "A link trace already exists for this item/user." +msgstr "" + +#: core/models.py:1051 +msgid "Item favorite" +msgstr "" + +#: core/models.py:1052 +msgid "Item favorites" +msgstr "" + +#: core/models.py:1058 +msgid "" +"This item is already targeted by a favorite relation instance for the same " +"user." +msgstr "" + +#: core/models.py:1080 +msgid "Item/user relation" +msgstr "" + +#: core/models.py:1081 +msgid "Item/user relations" +msgstr "" + +#: core/models.py:1087 +msgid "This user is already in this item." +msgstr "" + +#: core/models.py:1093 +msgid "This team is already in this item." +msgstr "" + +#: core/models.py:1099 +msgid "Either user or team must be set, not both." +msgstr "" + +#: core/models.py:1126 +msgid "email address" +msgstr "" + +#: core/models.py:1145 +msgid "Item invitation" +msgstr "" + +#: core/models.py:1146 +msgid "Item invitations" +msgstr "" + +#: core/templates/mail/html/invitation.html:162 +#: core/templates/mail/text/invitation.txt:3 +msgid "Logo email" +msgstr "" + +#: core/templates/mail/html/invitation.html:209 +#: core/templates/mail/text/invitation.txt:10 +msgid "Open" +msgstr "" + +#: core/templates/mail/html/invitation.html:226 +#: core/templates/mail/text/invitation.txt:14 +msgid "" +" Calendars, your new essential tool for organizing, sharing and collaborating as " +"a team. " +msgstr "" + +#: core/templates/mail/html/invitation.html:233 +#: core/templates/mail/text/invitation.txt:16 +#, python-format +msgid " Brought to you by %(brandname)s " +msgstr "" + +#: calendars/settings.py:250 +msgid "English" +msgstr "" + +#: calendars/settings.py:251 +msgid "French" +msgstr "" + +#: calendars/settings.py:252 +msgid "German" +msgstr "" diff --git a/src/backend/locale/fr_FR/LC_MESSAGES/django.po b/src/backend/locale/fr_FR/LC_MESSAGES/django.po new file mode 100644 index 0000000..88ce6cb --- /dev/null +++ b/src/backend/locale/fr_FR/LC_MESSAGES/django.po @@ -0,0 +1,371 @@ +msgid "" +msgstr "" +"Project-Id-Version: lasuite-docs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-05-19 15:10+0000\n" +"PO-Revision-Date: 2025-01-27 09:27\n" +"Last-Translator: \n" +"Language-Team: French\n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Crowdin-Project: lasuite-docs\n" +"X-Crowdin-Project-ID: 754523\n" +"X-Crowdin-Language: fr\n" +"X-Crowdin-File: backend-calendars.pot\n" +"X-Crowdin-File-ID: 18\n" + +#: core/admin.py:26 +msgid "Personal info" +msgstr "Infos Personnelles" + +#: core/admin.py:39 core/admin.py:119 +msgid "Permissions" +msgstr "" + +#: core/admin.py:51 +msgid "Important dates" +msgstr "Dates importantes" + +#: core/admin.py:129 +msgid "Tree structure" +msgstr "" + +#: core/api/filters.py:16 +msgid "Title" +msgstr "" + +#: core/api/filters.py:28 +msgid "Creator is me" +msgstr "" + +#: core/api/filters.py:31 +msgid "Favorite" +msgstr "" + +#: core/api/serializers.py:304 +msgid "An item with this title already exists in the current path." +msgstr "" + +#: core/api/serializers.py:397 +msgid "This field is required for files." +msgstr "" + +#: core/api/serializers.py:409 +msgid "This field is required for folders." +msgstr "" + +#: core/models.py:53 core/models.py:60 +msgid "Reader" +msgstr "Lecteur" + +#: core/models.py:54 core/models.py:61 +msgid "Editor" +msgstr "Éditeur" + +#: core/models.py:62 +msgid "Administrator" +msgstr "Administrateur" + +#: core/models.py:63 +msgid "Owner" +msgstr "Propriétaire" + +#: core/models.py:74 +msgid "Restricted" +msgstr "Restreint" + +#: core/models.py:78 +msgid "Authenticated" +msgstr "Authentifié" + +#: core/models.py:80 +msgid "Public" +msgstr "" + +#: core/models.py:86 +msgid "Folder" +msgstr "" + +#: core/models.py:87 +msgid "File" +msgstr "" + +#: core/models.py:93 +msgid "Pending" +msgstr "" + +#: core/models.py:94 +msgid "Uploaded" +msgstr "" + +#: core/models.py:116 +msgid "id" +msgstr "" + +#: core/models.py:117 +msgid "primary key for the record as UUID" +msgstr "" + +#: core/models.py:123 +msgid "created on" +msgstr "" + +#: core/models.py:124 +msgid "date and time at which a record was created" +msgstr "" + +#: core/models.py:129 +msgid "updated on" +msgstr "" + +#: core/models.py:130 +msgid "date and time at which a record was last updated" +msgstr "" + +#: core/models.py:166 +msgid "" +"We couldn't find a user with this sub but the email is already associated " +"with a registered user." +msgstr "" + +#: core/models.py:179 +msgid "" +"Enter a valid sub. This value may contain only letters, numbers, and @/./+/-/" +"_/: characters." +msgstr "" + +#: core/models.py:185 +msgid "sub" +msgstr "" + +#: core/models.py:187 +msgid "" +"Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: " +"characters only." +msgstr "" + +#: core/models.py:196 +msgid "full name" +msgstr "" + +#: core/models.py:197 +msgid "short name" +msgstr "" + +#: core/models.py:199 +msgid "identity email address" +msgstr "" + +#: core/models.py:204 +msgid "admin email address" +msgstr "" + +#: core/models.py:211 +msgid "language" +msgstr "" + +#: core/models.py:212 +msgid "The language in which the user wants to see the interface." +msgstr "" + +#: core/models.py:218 +msgid "The timezone in which the user wants to see times." +msgstr "" + +#: core/models.py:221 +msgid "device" +msgstr "" + +#: core/models.py:223 +msgid "Whether the user is a device or a real user." +msgstr "" + +#: core/models.py:226 +msgid "staff status" +msgstr "" + +#: core/models.py:228 +msgid "Whether the user can log into this admin site." +msgstr "" + +#: core/models.py:231 +msgid "active" +msgstr "" + +#: core/models.py:234 +msgid "" +"Whether this user should be treated as active. Unselect this instead of " +"deleting accounts." +msgstr "" + +#: core/models.py:246 +msgid "user" +msgstr "" + +#: core/models.py:247 +msgid "users" +msgstr "" + +#: core/models.py:269 +msgid "Workspace" +msgstr "" + +#: core/models.py:457 +msgid "Only folders can have children." +msgstr "" + +#: core/models.py:470 +msgid "title already exists in this folder." +msgstr "" + +#: core/models.py:504 +msgid "title" +msgstr "" + +#: core/models.py:549 +msgid "Item" +msgstr "" + +#: core/models.py:550 +msgid "Items" +msgstr "" + +#: core/models.py:815 +#, python-brace-format +msgid "{name} shared an item with you!" +msgstr "{name} a partagé un item avec vous!" + +#: core/models.py:817 +#, python-brace-format +msgid "{name} invited you with the role \"{role}\" on the following item:" +msgstr "{name} vous a invité avec le rôle \"{role}\" sur le item suivant:" + +#: core/models.py:820 +#, python-brace-format +#| msgid "{name} shared an item with you: {title}" +msgid "{name} shared an item with you: {title}" +msgstr "{name} a partagé un item avec vous: {title}" + +#: core/models.py:872 +msgid "This item is already hard deleted." +msgstr "" + +#: core/models.py:882 +msgid "To hard delete an item, it must first be soft deleted." +msgstr "" + +#: core/models.py:902 +msgid "This item is not deleted." +msgstr "" + +#: core/models.py:918 +msgid "This item was permanently deleted and cannot be restored." +msgstr "" + +#: core/models.py:968 +msgid "Only folders can be targeted when moving an item" +msgstr "" + +#: core/models.py:1021 +msgid "Item/user link trace" +msgstr "" + +#: core/models.py:1022 +msgid "Item/user link traces" +msgstr "" + +#: core/models.py:1028 +msgid "A link trace already exists for this item/user." +msgstr "" + +#: core/models.py:1051 +msgid "Item favorite" +msgstr "" + +#: core/models.py:1052 +msgid "Item favorites" +msgstr "" + +#: core/models.py:1058 +msgid "" +"This item is already targeted by a favorite relation instance for the same " +"user." +msgstr "" + +#: core/models.py:1080 +msgid "Item/user relation" +msgstr "" + +#: core/models.py:1081 +msgid "Item/user relations" +msgstr "" + +#: core/models.py:1087 +msgid "This user is already in this item." +msgstr "" + +#: core/models.py:1093 +msgid "This team is already in this item." +msgstr "" + +#: core/models.py:1099 +msgid "Either user or team must be set, not both." +msgstr "" + +#: core/models.py:1126 +msgid "email address" +msgstr "" + +#: core/models.py:1145 +msgid "Item invitation" +msgstr "" + +#: core/models.py:1146 +msgid "Item invitations" +msgstr "" + +#: core/templates/mail/html/invitation.html:162 +#: core/templates/mail/text/invitation.txt:3 +msgid "Logo email" +msgstr "" + +#: core/templates/mail/html/invitation.html:209 +#: core/templates/mail/text/invitation.txt:10 +msgid "Open" +msgstr "Ouvrir" + +#: core/templates/mail/html/invitation.html:226 +#: core/templates/mail/text/invitation.txt:14 +msgid "" +" Calendars, your new essential tool for organizing, sharing and collaborating as " +"a team. " +msgstr "" +"Fichiers, votre outil essentiel pour organiser, partager et collaborer en " +"équipe." + +#: core/templates/mail/html/invitation.html:233 +#: core/templates/mail/text/invitation.txt:16 +#, python-format +msgid " Brought to you by %(brandname)s " +msgstr " Proposé par %(brandname)s " + +#: calendars/settings.py:250 +msgid "English" +msgstr "" + +#: calendars/settings.py:251 +msgid "French" +msgstr "" + +#: calendars/settings.py:252 +msgid "German" +msgstr "" + +#~ msgid "A new item was created on your behalf!" +#~ msgstr "Un nouveau item a été créé pour vous !" + +#~ msgid "You have been granted ownership of a new item:" +#~ msgstr "Vous avez été déclaré propriétaire d'un nouveau item :" diff --git a/src/backend/locale/nl_NL/LC_MESSAGES/django.po b/src/backend/locale/nl_NL/LC_MESSAGES/django.po new file mode 100644 index 0000000..48e39e2 --- /dev/null +++ b/src/backend/locale/nl_NL/LC_MESSAGES/django.po @@ -0,0 +1,369 @@ +msgid "" +msgstr "" +"Project-Id-Version: lasuite-docs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-05-19 15:10+0000\n" +"PO-Revision-Date: 2025-01-27 09:27\n" +"Last-Translator: \n" +"Language-Team: Dutch\n" +"Language: nl_NL\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: lasuite-docs\n" +"X-Crowdin-Project-ID: 754523\n" +"X-Crowdin-Language: nl\n" +"X-Crowdin-File: backend-calendars.pot\n" +"X-Crowdin-File-ID: 18\n" + +#: core/admin.py:26 +msgid "Personal info" +msgstr "Persoonlijke gegevens" + +#: core/admin.py:39 core/admin.py:119 +msgid "Permissions" +msgstr "Machtigingen" + +#: core/admin.py:51 +msgid "Important dates" +msgstr "Belangrijke data" + +#: core/admin.py:129 +msgid "Tree structure" +msgstr "Boomstructuur" + +#: core/api/filters.py:16 +msgid "Title" +msgstr "Titel" + +#: core/api/filters.py:28 +msgid "Creator is me" +msgstr "Ik ben eigenaar" + +#: core/api/filters.py:31 +msgid "Favorite" +msgstr "Favoriet" + +#: core/api/serializers.py:304 +msgid "An item with this title already exists in the current path." +msgstr "Er bestaat al een item met deze titel in het huidige pad." + +#: core/api/serializers.py:397 +msgid "This field is required for files." +msgstr "Dit veld is verplicht voor bestanden" + +#: core/api/serializers.py:409 +msgid "This field is required for folders." +msgstr "Dit veld is verplicht voor mappen." + +#: core/models.py:53 core/models.py:60 +msgid "Reader" +msgstr "Lezer" + +#: core/models.py:54 core/models.py:61 +msgid "Editor" +msgstr "Redacteur" + +#: core/models.py:62 +msgid "Administrator" +msgstr "Beheerder" + +#: core/models.py:63 +msgid "Owner" +msgstr "Eigenaar" + +#: core/models.py:74 +msgid "Restricted" +msgstr "Beperkt" + +#: core/models.py:78 +msgid "Authenticated" +msgstr "Ingelogd" + +#: core/models.py:80 +msgid "Public" +msgstr "Openbaar" + +#: core/models.py:86 +msgid "Folder" +msgstr "Map" + +#: core/models.py:87 +msgid "File" +msgstr "Bestand" + +#: core/models.py:93 +msgid "Pending" +msgstr "In afwachting" + +#: core/models.py:94 +msgid "Uploaded" +msgstr "Geüpload" + +#: core/models.py:116 +msgid "id" +msgstr "id" + +#: core/models.py:117 +msgid "primary key for the record as UUID" +msgstr "primaire sleutel voor het record als UUID" + +#: core/models.py:123 +msgid "created on" +msgstr "gecreëerd op" + +#: core/models.py:124 +msgid "date and time at which a record was created" +msgstr "datum en tijd waarop een record is gemaakt" + +#: core/models.py:129 +msgid "updated on" +msgstr "bijgewerkt op" + +#: core/models.py:130 +msgid "date and time at which a record was last updated" +msgstr "datum en tijd waarop een record voor het laatst is bijgewerkt" + +#: core/models.py:166 +msgid "" +"We couldn't find a user with this sub but the email is already associated " +"with a registered user." +msgstr "We konden geen gebruiker vinden met deze id, maar het e-mailadres is al gekoppeld aan een geregistreerde gebruiker." + +#: core/models.py:179 +msgid "" +"Enter a valid sub. This value may contain only letters, numbers, and @/./+/-/" +"_/: characters." +msgstr "Voer een geldige sub in. Deze waarde mag alleen letters, cijfers en @/./+/-/_/: " +"tekens bevatten." + +#: core/models.py:185 +msgid "sub" +msgstr "id" + +#: core/models.py:187 +msgid "" +"Required. 255 characters or fewer. Letters, numbers, and @/./+/-/_/: " +"characters only." +msgstr "Verplicht. 255 tekens of minder. Alleen letters, cijfers en @/./+/-/_/: tekens." + +#: core/models.py:196 +msgid "full name" +msgstr "volledige naam" + +#: core/models.py:197 +msgid "short name" +msgstr "gebruikersnaam" + +#: core/models.py:199 +msgid "identity email address" +msgstr "identiteits e-mailadres" + +#: core/models.py:204 +msgid "admin email address" +msgstr "admin e-mailadres" + +#: core/models.py:211 +msgid "language" +msgstr "taal" + +#: core/models.py:212 +msgid "The language in which the user wants to see the interface." +msgstr "De taal waarin de gebruiker de interface wil zien." + +#: core/models.py:218 +msgid "The timezone in which the user wants to see times." +msgstr "Tijdzone waarin de gebruiker de tijd wil zien." + +#: core/models.py:221 +msgid "device" +msgstr "apparaat" + +#: core/models.py:223 +msgid "Whether the user is a device or a real user." +msgstr "Of de gebruiker een apparaat of een echte gebruiker is." + +#: core/models.py:226 +msgid "staff status" +msgstr "personeelsstatus" + +#: core/models.py:228 +msgid "Whether the user can log into this admin site." +msgstr "Of de gebruiker kan inloggen op deze beheer site." + +#: core/models.py:231 +msgid "active" +msgstr "actief" + +#: core/models.py:234 +msgid "" +"Whether this user should be treated as active. Unselect this instead of " +"deleting accounts." +msgstr "Of deze gebruiker als actief moet worden behandeld. Deselecteer dit in plaats van " +"accounts te verwijderen." + +#: core/models.py:246 +msgid "user" +msgstr "gebruiker" + +#: core/models.py:247 +msgid "users" +msgstr "gebruikers" + +#: core/models.py:269 +msgid "Workspace" +msgstr "Werkruimte" + +#: core/models.py:457 +msgid "Only folders can have children." +msgstr "Alleen mappen kunnen subitems hebben." + +#: core/models.py:470 +msgid "title already exists in this folder." +msgstr "titel bestaat al in deze map." + +#: core/models.py:504 +msgid "title" +msgstr "titel" + +#: core/models.py:549 +msgid "Item" +msgstr "Item" + +#: core/models.py:550 +msgid "Items" +msgstr "Items" + +#: core/models.py:815 +#, python-brace-format +msgid "{name} shared an item with you!" +msgstr "{name} heeft een item met je gedeeld!" + +#: core/models.py:817 +#, python-brace-format +msgid "{name} invited you with the role \"{role}\" on the following item:" +msgstr "{name} heeft je uitgenodigd met de rol \"{role}\" voor het volgende item:" + +#: core/models.py:820 +#, python-brace-format +msgid "{name} shared an item with you: {title}" +msgstr "{name} heeft een item met je gedeeld: {title}" + +#: core/models.py:872 +msgid "This item is already hard deleted." +msgstr "Dit item is al permanent verwijderd." + +#: core/models.py:882 +msgid "To hard delete an item, it must first be soft deleted." +msgstr "Om een item permanent te verwijderen, moet het eerst tijdelijk worden verwijderd." + +#: core/models.py:902 +msgid "This item is not deleted." +msgstr "Dit item is niet verwijderd." + +#: core/models.py:918 +msgid "This item was permanently deleted and cannot be restored." +msgstr "Dit item is permanent verwijderd en kan niet worden hersteld." + +#: core/models.py:968 +msgid "Only folders can be targeted when moving an item" +msgstr "Alleen mappen kunnen worden geselecteerd bij het verplaatsen van een item." + +#: core/models.py:1021 +msgid "Item/user link trace" +msgstr "Item/gebruiker link " + +#: core/models.py:1022 +msgid "Item/user link traces" +msgstr "Item/gebruiker link" + +#: core/models.py:1028 +msgid "A link trace already exists for this item/user." +msgstr "Er bestaat al een link trace voor dit item/gebruiker." + +#: core/models.py:1051 +msgid "Item favorite" +msgstr "Item favoriet" + +#: core/models.py:1052 +msgid "Item favorites" +msgstr "Item favorieten" + +#: core/models.py:1058 +msgid "" +"This item is already targeted by a favorite relation instance for the same " +"user." +msgstr "Dit item is al het doel van een favorietrelatie voor dezelfde " +"gebruiker." + +#: core/models.py:1080 +msgid "Item/user relation" +msgstr "Item/gebruiker relatie" + +#: core/models.py:1081 +msgid "Item/user relations" +msgstr "Item/gebruiker relaties" + +#: core/models.py:1087 +msgid "This user is already in this item." +msgstr "Deze gebruiker bestaat al in dit item." + +#: core/models.py:1093 +msgid "This team is already in this item." +msgstr "Dit team bestaat al in dit item." + +#: core/models.py:1099 +msgid "Either user or team must be set, not both." +msgstr "Ofwel gebruiker of team moet worden ingesteld, niet beide." + +#: core/models.py:1126 +msgid "email address" +msgstr "e-mailadres" + +#: core/models.py:1145 +msgid "Item invitation" +msgstr "Item uitnodiging" + +#: core/models.py:1146 +msgid "Item invitations" +msgstr "Item uitnodigingen" + +#: core/templates/mail/html/invitation.html:162 +#: core/templates/mail/text/invitation.txt:3 +msgid "Logo email" +msgstr "Logo e-mail" + +#: core/templates/mail/html/invitation.html:209 +#: core/templates/mail/text/invitation.txt:10 +msgid "Open" +msgstr "Open" + +#: core/templates/mail/html/invitation.html:226 +#: core/templates/mail/text/invitation.txt:14 +msgid "" +" Calendars, your new essential tool for organizing, sharing and collaborating as " +"a team. " +msgstr " Calendars, jouw nieuwe essentiële tool voor het organiseren, delen en samenwerken als team" + +#: core/templates/mail/html/invitation.html:233 +#: core/templates/mail/text/invitation.txt:16 +#, python-format +msgid " Brought to you by %(brandname)s " +msgstr " Aangeboden door %(brandname)s " + +#: calendars/settings.py:250 +msgid "English" +msgstr "Engels" + +#: calendars/settings.py:251 +msgid "French" +msgstr "Frans" + +#: calendars/settings.py:252 +msgid "German" +msgstr "Duits" + +#: calendars/settings.py:253 +msgid "Dutch" +msgstr "Nederlands" diff --git a/src/backend/manage.py b/src/backend/manage.py new file mode 100644 index 0000000..c590546 --- /dev/null +++ b/src/backend/manage.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +""" +calendars' management script. +""" + +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "calendars.settings") + os.environ.setdefault("DJANGO_CONFIGURATION", "Development") + + from configurations.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml new file mode 100644 index 0000000..7e103e8 --- /dev/null +++ b/src/backend/pyproject.toml @@ -0,0 +1,145 @@ +# +# calendar package +# +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "calendars" +version = "0.10.1" +authors = [{ "name" = "anct", "email" = "contact@suite.anct.gouv.fr" }] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Framework :: Django", + "Framework :: Django :: 5", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.13", +] +description = "A calendar application." +keywords = ["Django", "Contacts", "Templates", "RBAC"] +license = { file = "LICENSE" } +readme = "README.md" +requires-python = "~=3.13.0" +dependencies = [ + "Brotli==1.2.0", + "dj-database-url==3.0.1", + "caldav==2.2.3", + "celery[redis]==5.6.0", + "django==5.2.9", + "django-celery-beat==2.8.1", + "django-configurations==2.5.1", + "django-cors-headers==4.9.0", + "django-countries==8.2.0", + "django-filter==25.2", + "django-lasuite[all]==0.0.21", + "django-parler==2.3", + "django-redis==6.0.0", + "django-timezone-field>=5.1", + "djangorestframework==3.16.1", + "djangorestframework-api-key==3.1.0", + "drf_spectacular==0.29.0", + "drf-standardized-errors==0.15.0", + "factory_boy==3.3.3", + "gunicorn==23.0.0", + "jsonschema==4.25.1", + "mozilla-django-oidc==4.0.1", + "nested-multipart-parser==1.6.0", + "pillow>=10.0", + "psycopg[binary]==3.3.1", + "PyJWT==2.10.1", + "redis<6.0.0", + "requests==2.32.5", + "sentry-sdk==2.46.0", + "url-normalize==2.2.1", + "whitenoise==6.11.0", +] + +[project.urls] +"Bug Tracker" = "https://github.com/suitenumerique/calendars/issues/new" +"Changelog" = "https://github.com/suitenumerique/calendars/blob/main/CHANGELOG.md" +"Homepage" = "https://github.com/suitenumerique/calendars" +"Repository" = "https://github.com/suitenumerique/calendars" + +[project.optional-dependencies] +dev = [ + "django-debug-toolbar==6.1.0", + "django-extensions==4.1", + "drf-spectacular-sidecar==2025.12.1", + "freezegun==1.5.5", + "ipdb==0.13.13", + "ipython==9.7.0", + "pyfakefs==5.10.2", + "pylint-django==2.6.1", + "pylint<4.0.0", + "pytest-cov==7.0.0", + "pytest-django==4.11.1", + "pytest==9.0.1", + "pytest-icdiff==0.9", + "pytest-xdist==3.8.0", + "responses==0.25.8", + "ruff==0.14.7", + "types-requests==2.32.4.20250913", +] + +[tool.setuptools] +packages = { find = { where = ["."], exclude = ["tests"] } } +zip-safe = true + +[tool.distutils.bdist_wheel] +universal = true + +[tool.ruff] +exclude = [ + ".git", + ".venv", + "build", + "venv", + "__pycache__", + "*/migrations/*", +] +line-length = 88 + + +[tool.ruff.lint] +ignore = ["DJ001", "PLR2004"] +select = [ + "B", # flake8-bugbear + "BLE", # flake8-blind-except + "C4", # flake8-comprehensions + "DJ", # flake8-django + "I", # isort + "PLC", # pylint-convention + "PLE", # pylint-error + "PLR", # pylint-refactoring + "PLW", # pylint-warning + "RUF100", # Ruff unused-noqa + "RUF200", # Ruff check pyproject.toml + "S", # flake8-bandit + "SLF", # flake8-self + "T20", # flake8-print +] + +[tool.ruff.lint.isort] +section-order = ["future","standard-library","django","third-party","calendars","first-party","local-folder"] +sections = { calendars=["core", "caldav"], django=["django"] } +extra-standard-library = ["tomllib"] + +[tool.ruff.lint.per-file-ignores] +"**/tests/*" = ["S", "SLF"] + +[tool.pytest.ini_options] +addopts = [ + "-v", + "--cov-report", + "term-missing", + # Allow test files to have the same name in different directories. + "--import-mode=importlib", +] +python_files = [ + "test_*.py", + "tests.py", +] diff --git a/src/backend/uv.lock b/src/backend/uv.lock new file mode 100644 index 0000000..75a22da --- /dev/null +++ b/src/backend/uv.lock @@ -0,0 +1,1836 @@ +version = 1 +revision = 3 +requires-python = "==3.13.*" + +[[package]] +name = "amqp" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/fc/ec94a357dfc6683d8c86f8b4cfa5416a4c36b28052ec8260c77aca96a443/amqp-5.3.1.tar.gz", hash = "sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432", size = 129013, upload-time = "2024-11-12T19:55:44.051Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/99/fc813cd978842c26c82534010ea849eee9ab3a13ea2b74e95cb9c99e747b/amqp-5.3.1-py3-none-any.whl", hash = "sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2", size = 50944, upload-time = "2024-11-12T19:55:41.782Z" }, +] + +[[package]] +name = "asgiref" +version = "3.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/b9/4db2509eabd14b4a8c71d1b24c8d5734c52b8560a7b1e1a8b56c8d25568b/asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4", size = 37969, upload-time = "2025-11-19T15:32:20.106Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/be/317c2c55b8bbec407257d45f5c8d1b6867abc76d12043f2d3d58c538a4ea/asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d", size = 24096, upload-time = "2025-11-19T15:32:19.004Z" }, +] + +[[package]] +name = "astroid" +version = "3.3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/74/dfb75f9ccd592bbedb175d4a32fc643cf569d7c218508bfbd6ea7ef9c091/astroid-3.3.11.tar.gz", hash = "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce", size = 400439, upload-time = "2025-07-13T18:04:23.177Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/0f/3b8fdc946b4d9cc8cc1e8af42c4e409468c84441b933d037e101b3d72d86/astroid-3.3.11-py3-none-any.whl", hash = "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec", size = 275612, upload-time = "2025-07-13T18:04:21.07Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "billiard" +version = "4.2.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/23/b12ac0bcdfb7360d664f40a00b1bda139cbbbced012c34e375506dbd0143/billiard-4.2.4.tar.gz", hash = "sha256:55f542c371209e03cd5862299b74e52e4fbcba8250ba611ad94276b369b6a85f", size = 156537, upload-time = "2025-11-30T13:28:48.52Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/87/8bab77b323f16d67be364031220069f79159117dd5e43eeb4be2fef1ac9b/billiard-4.2.4-py3-none-any.whl", hash = "sha256:525b42bdec68d2b983347ac312f892db930858495db601b5836ac24e6477cde5", size = 87070, upload-time = "2025-11-30T13:28:47.016Z" }, +] + +[[package]] +name = "brotli" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/16/c92ca344d646e71a43b8bb353f0a6490d7f6e06210f8554c8f874e454285/brotli-1.2.0.tar.gz", hash = "sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a", size = 7388632, upload-time = "2025-11-05T18:39:42.86Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/d4/4ad5432ac98c73096159d9ce7ffeb82d151c2ac84adcc6168e476bb54674/brotli-1.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9e5825ba2c9998375530504578fd4d5d1059d09621a02065d1b6bfc41a8e05ab", size = 861523, upload-time = "2025-11-05T18:38:34.67Z" }, + { url = "https://files.pythonhosted.org/packages/91/9f/9cc5bd03ee68a85dc4bc89114f7067c056a3c14b3d95f171918c088bf88d/brotli-1.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c", size = 444289, upload-time = "2025-11-05T18:38:35.6Z" }, + { url = "https://files.pythonhosted.org/packages/2e/b6/fe84227c56a865d16a6614e2c4722864b380cb14b13f3e6bef441e73a85a/brotli-1.2.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8565e3cdc1808b1a34714b553b262c5de5fbda202285782173ec137fd13709f", size = 1528076, upload-time = "2025-11-05T18:38:36.639Z" }, + { url = "https://files.pythonhosted.org/packages/55/de/de4ae0aaca06c790371cf6e7ee93a024f6b4bb0568727da8c3de112e726c/brotli-1.2.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:26e8d3ecb0ee458a9804f47f21b74845cc823fd1bb19f02272be70774f56e2a6", size = 1626880, upload-time = "2025-11-05T18:38:37.623Z" }, + { url = "https://files.pythonhosted.org/packages/5f/16/a1b22cbea436642e071adcaf8d4b350a2ad02f5e0ad0da879a1be16188a0/brotli-1.2.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67a91c5187e1eec76a61625c77a6c8c785650f5b576ca732bd33ef58b0dff49c", size = 1419737, upload-time = "2025-11-05T18:38:38.729Z" }, + { url = "https://files.pythonhosted.org/packages/46/63/c968a97cbb3bdbf7f974ef5a6ab467a2879b82afbc5ffb65b8acbb744f95/brotli-1.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ecdb3b6dc36e6d6e14d3a1bdc6c1057c8cbf80db04031d566eb6080ce283a48", size = 1484440, upload-time = "2025-11-05T18:38:39.916Z" }, + { url = "https://files.pythonhosted.org/packages/06/9d/102c67ea5c9fc171f423e8399e585dabea29b5bc79b05572891e70013cdd/brotli-1.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3e1b35d56856f3ed326b140d3c6d9db91740f22e14b06e840fe4bb1923439a18", size = 1593313, upload-time = "2025-11-05T18:38:41.24Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4a/9526d14fa6b87bc827ba1755a8440e214ff90de03095cacd78a64abe2b7d/brotli-1.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:54a50a9dad16b32136b2241ddea9e4df159b41247b2ce6aac0b3276a66a8f1e5", size = 1487945, upload-time = "2025-11-05T18:38:42.277Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e8/3fe1ffed70cbef83c5236166acaed7bb9c766509b157854c80e2f766b38c/brotli-1.2.0-cp313-cp313-win32.whl", hash = "sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a", size = 334368, upload-time = "2025-11-05T18:38:43.345Z" }, + { url = "https://files.pythonhosted.org/packages/ff/91/e739587be970a113b37b821eae8097aac5a48e5f0eca438c22e4c7dd8648/brotli-1.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:b63daa43d82f0cdabf98dee215b375b4058cce72871fd07934f179885aad16e8", size = 369116, upload-time = "2025-11-05T18:38:44.609Z" }, +] + +[[package]] +name = "caldav" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "icalendar" }, + { name = "icalendar-searcher" }, + { name = "lxml" }, + { name = "niquests" }, + { name = "recurring-ical-events" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/b9/32c2dedc33d69e01608c42572e86e47511a18a2e2fdb6431e5e5682aba8e/caldav-2.2.3.tar.gz", hash = "sha256:d53e2de4e4aee9e317b23073de6de153077729a40add1a2b2107af5a0db0949c", size = 10072173, upload-time = "2025-12-06T21:18:19.386Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/b3/a16ed3bc5cbcdd269eaea4ae01d1c1a1cab2107dd0f1750043051194a4b0/caldav-2.2.3-py2.py3-none-any.whl", hash = "sha256:0fc5d375a15e469817ffa21276cab372f776d15dc4ba4a3ad34c3e43024f5c67", size = 121169, upload-time = "2025-12-06T21:18:08.288Z" }, +] + +[[package]] +name = "calendars" +version = "0.10.1" +source = { editable = "." } +dependencies = [ + { name = "brotli" }, + { name = "caldav" }, + { name = "celery", extra = ["redis"] }, + { name = "dj-database-url" }, + { name = "django" }, + { name = "django-celery-beat" }, + { name = "django-configurations" }, + { name = "django-cors-headers" }, + { name = "django-countries" }, + { name = "django-filter" }, + { name = "django-lasuite", extra = ["all"] }, + { name = "django-parler" }, + { name = "django-redis" }, + { name = "django-timezone-field" }, + { name = "djangorestframework" }, + { name = "djangorestframework-api-key" }, + { name = "drf-spectacular" }, + { name = "drf-standardized-errors" }, + { name = "factory-boy" }, + { name = "gunicorn" }, + { name = "jsonschema" }, + { name = "mozilla-django-oidc" }, + { name = "nested-multipart-parser" }, + { name = "pillow" }, + { name = "psycopg", extra = ["binary"] }, + { name = "pyjwt" }, + { name = "redis" }, + { name = "requests" }, + { name = "sentry-sdk" }, + { name = "url-normalize" }, + { name = "whitenoise" }, +] + +[package.optional-dependencies] +dev = [ + { name = "django-debug-toolbar" }, + { name = "django-extensions" }, + { name = "drf-spectacular-sidecar" }, + { name = "freezegun" }, + { name = "ipdb" }, + { name = "ipython" }, + { name = "pyfakefs" }, + { name = "pylint" }, + { name = "pylint-django" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "pytest-icdiff" }, + { name = "pytest-xdist" }, + { name = "responses" }, + { name = "ruff" }, + { name = "types-requests" }, +] + +[package.metadata] +requires-dist = [ + { name = "brotli", specifier = "==1.2.0" }, + { name = "caldav", specifier = "==2.2.3" }, + { name = "celery", extras = ["redis"], specifier = "==5.6.0" }, + { name = "dj-database-url", specifier = "==3.0.1" }, + { name = "django", specifier = "==5.2.9" }, + { name = "django-celery-beat", specifier = "==2.8.1" }, + { name = "django-configurations", specifier = "==2.5.1" }, + { name = "django-cors-headers", specifier = "==4.9.0" }, + { name = "django-countries", specifier = "==8.2.0" }, + { name = "django-debug-toolbar", marker = "extra == 'dev'", specifier = "==6.1.0" }, + { name = "django-extensions", marker = "extra == 'dev'", specifier = "==4.1" }, + { name = "django-filter", specifier = "==25.2" }, + { name = "django-lasuite", extras = ["all"], specifier = "==0.0.21" }, + { name = "django-parler", specifier = "==2.3" }, + { name = "django-redis", specifier = "==6.0.0" }, + { name = "django-timezone-field", specifier = ">=5.1" }, + { name = "djangorestframework", specifier = "==3.16.1" }, + { name = "djangorestframework-api-key", specifier = "==3.1.0" }, + { name = "drf-spectacular", specifier = "==0.29.0" }, + { name = "drf-spectacular-sidecar", marker = "extra == 'dev'", specifier = "==2025.12.1" }, + { name = "drf-standardized-errors", specifier = "==0.15.0" }, + { name = "factory-boy", specifier = "==3.3.3" }, + { name = "freezegun", marker = "extra == 'dev'", specifier = "==1.5.5" }, + { name = "gunicorn", specifier = "==23.0.0" }, + { name = "ipdb", marker = "extra == 'dev'", specifier = "==0.13.13" }, + { name = "ipython", marker = "extra == 'dev'", specifier = "==9.7.0" }, + { name = "jsonschema", specifier = "==4.25.1" }, + { name = "mozilla-django-oidc", specifier = "==4.0.1" }, + { name = "nested-multipart-parser", specifier = "==1.6.0" }, + { name = "pillow", specifier = ">=10.0" }, + { name = "psycopg", extras = ["binary"], specifier = "==3.3.1" }, + { name = "pyfakefs", marker = "extra == 'dev'", specifier = "==5.10.2" }, + { name = "pyjwt", specifier = "==2.10.1" }, + { name = "pylint", marker = "extra == 'dev'", specifier = "<4.0.0" }, + { name = "pylint-django", marker = "extra == 'dev'", specifier = "==2.6.1" }, + { name = "pytest", marker = "extra == 'dev'", specifier = "==9.0.1" }, + { name = "pytest-cov", marker = "extra == 'dev'", specifier = "==7.0.0" }, + { name = "pytest-django", marker = "extra == 'dev'", specifier = "==4.11.1" }, + { name = "pytest-icdiff", marker = "extra == 'dev'", specifier = "==0.9" }, + { name = "pytest-xdist", marker = "extra == 'dev'", specifier = "==3.8.0" }, + { name = "redis", specifier = "<6.0.0" }, + { name = "requests", specifier = "==2.32.5" }, + { name = "responses", marker = "extra == 'dev'", specifier = "==0.25.8" }, + { name = "ruff", marker = "extra == 'dev'", specifier = "==0.14.7" }, + { name = "sentry-sdk", specifier = "==2.46.0" }, + { name = "types-requests", marker = "extra == 'dev'", specifier = "==2.32.4.20250913" }, + { name = "url-normalize", specifier = "==2.2.1" }, + { name = "whitenoise", specifier = "==6.11.0" }, +] +provides-extras = ["dev"] + +[[package]] +name = "celery" +version = "5.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "billiard" }, + { name = "click" }, + { name = "click-didyoumean" }, + { name = "click-plugins" }, + { name = "click-repl" }, + { name = "exceptiongroup" }, + { name = "kombu" }, + { name = "python-dateutil" }, + { name = "tzlocal" }, + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/5f/b681ae3c89290d2ea6562ea96b40f5af6f6fc5f7743e2cd1a19e47721548/celery-5.6.0.tar.gz", hash = "sha256:641405206042d52ae460e4e9751a2e31b06cf80ab836fcf92e0b9311d7ea8113", size = 1712522, upload-time = "2025-11-30T17:39:46.282Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/01/4e/53a125038d6a814491a0ae3457435c13cf8821eb602292cf9db37ce35f62/celery-5.6.0-py3-none-any.whl", hash = "sha256:33cf01477b175017fc8f22c5ee8a65157591043ba8ca78a443fe703aa910f581", size = 444561, upload-time = "2025-11-30T17:39:44.314Z" }, +] + +[package.optional-dependencies] +redis = [ + { name = "kombu", extra = ["redis"] }, +] + +[[package]] +name = "certifi" +version = "2025.11.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "click-didyoumean" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/ce/217289b77c590ea1e7c24242d9ddd6e249e52c795ff10fac2c50062c48cb/click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463", size = 3089, upload-time = "2024-03-24T08:22:07.499Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/5b/974430b5ffdb7a4f1941d13d83c64a0395114503cc357c6b9ae4ce5047ed/click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c", size = 3631, upload-time = "2024-03-24T08:22:06.356Z" }, +] + +[[package]] +name = "click-plugins" +version = "1.1.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/a4/34847b59150da33690a36da3681d6bbc2ec14ee9a846bc30a6746e5984e4/click_plugins-1.1.1.2.tar.gz", hash = "sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261", size = 8343, upload-time = "2025-06-25T00:47:37.555Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/9a/2abecb28ae875e39c8cad711eb1186d8d14eab564705325e77e4e6ab9ae5/click_plugins-1.1.1.2-py2.py3-none-any.whl", hash = "sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6", size = 11051, upload-time = "2025-06-25T00:47:36.731Z" }, +] + +[[package]] +name = "click-repl" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/a2/57f4ac79838cfae6912f997b4d1a64a858fb0c86d7fcaae6f7b58d267fca/click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", size = 10449, upload-time = "2023-06-15T12:43:51.141Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/40/9d857001228658f0d59e97ebd4c346fe73e138c6de1bce61dc568a57c7f8/click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812", size = 10289, upload-time = "2023-06-15T12:43:48.626Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "coverage" +version = "7.13.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/23/f9/e92df5e07f3fc8d4c7f9a0f146ef75446bf870351cd37b788cf5897f8079/coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", size = 825862, upload-time = "2025-12-28T15:42:56.969Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", size = 218951, upload-time = "2025-12-28T15:41:16.653Z" }, + { url = "https://files.pythonhosted.org/packages/32/33/7cbfe2bdc6e2f03d6b240d23dc45fdaf3fd270aaf2d640be77b7f16989ab/coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", size = 219325, upload-time = "2025-12-28T15:41:18.609Z" }, + { url = "https://files.pythonhosted.org/packages/59/f6/efdabdb4929487baeb7cb2a9f7dac457d9356f6ad1b255be283d58b16316/coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", size = 250309, upload-time = "2025-12-28T15:41:20.629Z" }, + { url = "https://files.pythonhosted.org/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", size = 252907, upload-time = "2025-12-28T15:41:22.257Z" }, + { url = "https://files.pythonhosted.org/packages/75/38/f1ea837e3dc1231e086db1638947e00d264e7e8c41aa8ecacf6e1e0c05f4/coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", size = 254148, upload-time = "2025-12-28T15:41:23.87Z" }, + { url = "https://files.pythonhosted.org/packages/7f/43/f4f16b881aaa34954ba446318dea6b9ed5405dd725dd8daac2358eda869a/coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", size = 250515, upload-time = "2025-12-28T15:41:25.437Z" }, + { url = "https://files.pythonhosted.org/packages/84/34/8cba7f00078bd468ea914134e0144263194ce849ec3baad187ffb6203d1c/coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766", size = 252292, upload-time = "2025-12-28T15:41:28.459Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a4/cffac66c7652d84ee4ac52d3ccb94c015687d3b513f9db04bfcac2ac800d/coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", size = 250242, upload-time = "2025-12-28T15:41:30.02Z" }, + { url = "https://files.pythonhosted.org/packages/f4/78/9a64d462263dde416f3c0067efade7b52b52796f489b1037a95b0dc389c9/coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", size = 250068, upload-time = "2025-12-28T15:41:32.007Z" }, + { url = "https://files.pythonhosted.org/packages/69/c8/a8994f5fece06db7c4a97c8fc1973684e178599b42e66280dded0524ef00/coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", size = 251846, upload-time = "2025-12-28T15:41:33.946Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f7/91fa73c4b80305c86598a2d4e54ba22df6bf7d0d97500944af7ef155d9f7/coverage-7.13.1-cp313-cp313-win32.whl", hash = "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461", size = 221512, upload-time = "2025-12-28T15:41:35.519Z" }, + { url = "https://files.pythonhosted.org/packages/45/0b/0768b4231d5a044da8f75e097a8714ae1041246bb765d6b5563bab456735/coverage-7.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500", size = 222321, upload-time = "2025-12-28T15:41:37.371Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b8/bdcb7253b7e85157282450262008f1366aa04663f3e3e4c30436f596c3e2/coverage-7.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9", size = 220949, upload-time = "2025-12-28T15:41:39.553Z" }, + { url = "https://files.pythonhosted.org/packages/70/52/f2be52cc445ff75ea8397948c96c1b4ee14f7f9086ea62fc929c5ae7b717/coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", size = 219643, upload-time = "2025-12-28T15:41:41.567Z" }, + { url = "https://files.pythonhosted.org/packages/47/79/c85e378eaa239e2edec0c5523f71542c7793fe3340954eafb0bc3904d32d/coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", size = 219997, upload-time = "2025-12-28T15:41:43.418Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9b/b1ade8bfb653c0bbce2d6d6e90cc6c254cbb99b7248531cc76253cb4da6d/coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", size = 261296, upload-time = "2025-12-28T15:41:45.207Z" }, + { url = "https://files.pythonhosted.org/packages/1f/af/ebf91e3e1a2473d523e87e87fd8581e0aa08741b96265730e2d79ce78d8d/coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", size = 263363, upload-time = "2025-12-28T15:41:47.163Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8b/fb2423526d446596624ac7fde12ea4262e66f86f5120114c3cfd0bb2befa/coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", size = 265783, upload-time = "2025-12-28T15:41:49.03Z" }, + { url = "https://files.pythonhosted.org/packages/9b/26/ef2adb1e22674913b89f0fe7490ecadcef4a71fa96f5ced90c60ec358789/coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", size = 260508, upload-time = "2025-12-28T15:41:51.035Z" }, + { url = "https://files.pythonhosted.org/packages/ce/7d/f0f59b3404caf662e7b5346247883887687c074ce67ba453ea08c612b1d5/coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", size = 263357, upload-time = "2025-12-28T15:41:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b1/29896492b0b1a047604d35d6fa804f12818fa30cdad660763a5f3159e158/coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", size = 260978, upload-time = "2025-12-28T15:41:54.589Z" }, + { url = "https://files.pythonhosted.org/packages/48/f2/971de1238a62e6f0a4128d37adadc8bb882ee96afbe03ff1570291754629/coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", size = 259877, upload-time = "2025-12-28T15:41:56.263Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fc/0474efcbb590ff8628830e9aaec5f1831594874360e3251f1fdec31d07a3/coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", size = 262069, upload-time = "2025-12-28T15:41:58.093Z" }, + { url = "https://files.pythonhosted.org/packages/88/4f/3c159b7953db37a7b44c0eab8a95c37d1aa4257c47b4602c04022d5cb975/coverage-7.13.1-cp313-cp313t-win32.whl", hash = "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842", size = 222184, upload-time = "2025-12-28T15:41:59.763Z" }, + { url = "https://files.pythonhosted.org/packages/58/a5/6b57d28f81417f9335774f20679d9d13b9a8fb90cd6160957aa3b54a2379/coverage-7.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2", size = 223250, upload-time = "2025-12-28T15:42:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/81/7c/160796f3b035acfbb58be80e02e484548595aa67e16a6345e7910ace0a38/coverage-7.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09", size = 221521, upload-time = "2025-12-28T15:42:03.275Z" }, + { url = "https://files.pythonhosted.org/packages/cc/48/d9f421cb8da5afaa1a64570d9989e00fb7955e6acddc5a12979f7666ef60/coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", size = 210722, upload-time = "2025-12-28T15:42:54.901Z" }, +] + +[[package]] +name = "cron-descriptor" +version = "2.0.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/31/0b21d1599656b2ffa6043e51ca01041cd1c0f6dacf5a3e2b620ed120e7d8/cron_descriptor-2.0.6.tar.gz", hash = "sha256:e39d2848e1d8913cfb6e3452e701b5eec662ee18bea8cc5aa53ee1a7bb217157", size = 49456, upload-time = "2025-09-03T16:30:22.434Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/21/cc/361326a54ad92e2e12845ad15e335a4e14b8953665007fb514d3393dfb0f/cron_descriptor-2.0.6-py3-none-any.whl", hash = "sha256:3a1c0d837c0e5a32e415f821b36cf758eb92d510e6beff8fbfe4fa16573d93d6", size = 74446, upload-time = "2025-09-03T16:30:21.397Z" }, +] + +[[package]] +name = "cryptography" +version = "46.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" }, + { url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" }, + { url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" }, + { url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" }, + { url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" }, + { url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" }, + { url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" }, + { url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" }, + { url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" }, + { url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" }, + { url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" }, + { url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" }, + { url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" }, + { url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" }, + { url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" }, + { url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" }, + { url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" }, + { url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" }, + { url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" }, + { url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" }, + { url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" }, + { url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "dill" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, +] + +[[package]] +name = "dj-database-url" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/75/05/2ec51009f4ce424877dbd8ad95868faec0c3494ed0ff1635f9ab53d9e0ee/dj_database_url-3.0.1.tar.gz", hash = "sha256:8994961efb888fc6bf8c41550870c91f6f7691ca751888ebaa71442b7f84eff8", size = 12556, upload-time = "2025-07-02T09:40:11.424Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/5e/86a43c6fdaa41c12d58e4ff3ebbfd6b71a7cb0360a08614e3754ef2e9afb/dj_database_url-3.0.1-py3-none-any.whl", hash = "sha256:43950018e1eeea486bf11136384aec0fe55b29fe6fd8a44553231b85661d9383", size = 8808, upload-time = "2025-07-02T09:40:26.326Z" }, +] + +[[package]] +name = "django" +version = "5.2.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "sqlparse" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/1c/188ce85ee380f714b704283013434976df8d3a2df8e735221a02605b6794/django-5.2.9.tar.gz", hash = "sha256:16b5ccfc5e8c27e6c0561af551d2ea32852d7352c67d452ae3e76b4f6b2ca495", size = 10848762, upload-time = "2025-12-02T14:01:08.418Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/b0/7f42bfc38b8f19b78546d47147e083ed06e12fc29c42da95655e0962c6c2/django-5.2.9-py3-none-any.whl", hash = "sha256:3a4ea88a70370557ab1930b332fd2887a9f48654261cdffda663fef5976bb00a", size = 8290652, upload-time = "2025-12-02T14:01:03.485Z" }, +] + +[[package]] +name = "django-celery-beat" +version = "2.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "celery" }, + { name = "cron-descriptor" }, + { name = "django" }, + { name = "django-timezone-field" }, + { name = "python-crontab" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/11/0c8b412869b4fda72828572068312b10aafe7ccef7b41af3633af31f9d4b/django_celery_beat-2.8.1.tar.gz", hash = "sha256:dfad0201c0ac50c91a34700ef8fa0a10ee098cc7f3375fe5debed79f2204f80a", size = 175802, upload-time = "2025-05-13T06:58:29.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/e5/3a0167044773dee989b498e9a851fc1663bea9ab879f1179f7b8a827ac10/django_celery_beat-2.8.1-py3-none-any.whl", hash = "sha256:da2b1c6939495c05a551717509d6e3b79444e114a027f7b77bf3727c2a39d171", size = 104833, upload-time = "2025-05-13T06:58:27.309Z" }, +] + +[[package]] +name = "django-configurations" +version = "2.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/67/5fec7c64118209b20bde6b6f8a82300d9f4a56f7303293e2b31f9940e721/django-configurations-2.5.1.tar.gz", hash = "sha256:6e5083757e2bbdf9bb7850567536b96a93515f6b17503d74928ff628db2e0e94", size = 43225, upload-time = "2024-03-27T11:40:53.134Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/4e/1cc7fd6c0292d56e104f0c8c54ed71c35cafa06838d8f910b918589bf596/django_configurations-2.5.1-py3-none-any.whl", hash = "sha256:ceb84858da2dac846b15e715c2fd936cfc4c7917c074aff8d31700564093955e", size = 17357, upload-time = "2024-03-27T11:42:02.951Z" }, +] + +[[package]] +name = "django-cors-headers" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/39/55822b15b7ec87410f34cd16ce04065ff390e50f9e29f31d6d116fc80456/django_cors_headers-4.9.0.tar.gz", hash = "sha256:fe5d7cb59fdc2c8c646ce84b727ac2bca8912a247e6e68e1fb507372178e59e8", size = 21458, upload-time = "2025-09-18T10:40:52.326Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/d8/19ed1e47badf477d17fb177c1c19b5a21da0fd2d9f093f23be3fb86c5fab/django_cors_headers-4.9.0-py3-none-any.whl", hash = "sha256:15c7f20727f90044dcee2216a9fd7303741a864865f0c3657e28b7056f61b449", size = 12809, upload-time = "2025-09-18T10:40:50.843Z" }, +] + +[[package]] +name = "django-countries" +version = "8.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/67/2e/ed67f8f460d1de25ee64fca5d7f219680f944fc8ac5a29fbede3574dc3db/django_countries-8.2.0.tar.gz", hash = "sha256:6df3883180599052c7dfa9a8be0601792441cfb248935dc229ad1ac92e9e39e3", size = 2455542, upload-time = "2025-11-24T19:57:08.071Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/3c/9ebd7ed021b7c519bac954bc88146bc870e7d3c8db2580fa67268464fd2e/django_countries-8.2.0-py3-none-any.whl", hash = "sha256:2b2617bec7c15dc735bdec38ae89f0058e38fddfffdb19a7f6b75ef1e3d5380f", size = 3776079, upload-time = "2025-11-24T19:57:05.576Z" }, +] + +[[package]] +name = "django-debug-toolbar" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "sqlparse" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/50/acae2dd379164f6f4c6b6b36fd48a4d21b02095a03f4df7c30a8d1f1a62c/django_debug_toolbar-6.1.0.tar.gz", hash = "sha256:e962ec350c9be8bdba918138e975a9cdb193f60ec396af2bb71b769e8e165519", size = 309141, upload-time = "2025-10-30T19:50:39.458Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/72/685c978af45ad08257e2c69687a873eda6b6531c79b6e6091794c41c5ff6/django_debug_toolbar-6.1.0-py3-none-any.whl", hash = "sha256:e214dea4494087e7cebdcea84223819c5eb97f9de3110a3665ad673f0ba98413", size = 269069, upload-time = "2025-10-30T19:50:37.71Z" }, +] + +[[package]] +name = "django-extensions" +version = "4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/b3/ed0f54ed706ec0b54fd251cc0364a249c6cd6c6ec97f04dc34be5e929eac/django_extensions-4.1.tar.gz", hash = "sha256:7b70a4d28e9b840f44694e3f7feb54f55d495f8b3fa6c5c0e5e12bcb2aa3cdeb", size = 283078, upload-time = "2025-04-11T01:15:39.617Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/96/d967ca440d6a8e3861120f51985d8e5aec79b9a8bdda16041206adfe7adc/django_extensions-4.1-py3-none-any.whl", hash = "sha256:0699a7af28f2523bf8db309a80278519362cd4b6e1fd0a8cd4bf063e1e023336", size = 232980, upload-time = "2025-04-11T01:15:37.701Z" }, +] + +[[package]] +name = "django-filter" +version = "25.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/e4/465d2699cd388c0005fb8d6ae6709f239917c6d8790ac35719676fffdcf3/django_filter-25.2.tar.gz", hash = "sha256:760e984a931f4468d096f5541787efb8998c61217b73006163bf2f9523fe8f23", size = 143818, upload-time = "2025-10-05T09:51:31.521Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/40/6a02495c5658beb1f31eb09952d8aa12ef3c2a66342331ce3a35f7132439/django_filter-25.2-py3-none-any.whl", hash = "sha256:9c0f8609057309bba611062fe1b720b4a873652541192d232dd28970383633e3", size = 94145, upload-time = "2025-10-05T09:51:29.728Z" }, +] + +[[package]] +name = "django-lasuite" +version = "0.0.21" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "djangorestframework" }, + { name = "joserfc" }, + { name = "mozilla-django-oidc" }, + { name = "requests" }, + { name = "requests-toolbelt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/89/3b/b75a5767616d8f1781a9710b5bc3edd77c92b58bd6773dc9c972d45ea307/django_lasuite-0.0.21.tar.gz", hash = "sha256:99af5b38dd78eb0b80500a27eb352494682ea68ae5836795ae36a7962bca4dd1", size = 31772, upload-time = "2025-12-04T15:12:01.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/fd/07f555c576b2d61f7e1444261055b2c7dcc208676b5e2cb53405946fef53/django_lasuite-0.0.21-py3-none-any.whl", hash = "sha256:039db5784bae1e6cb34f718fa12d749a263d8642de68f9fb72ea62226257b144", size = 47572, upload-time = "2025-12-04T15:12:00.443Z" }, +] + +[package.optional-dependencies] +all = [ + { name = "celery" }, + { name = "django-configurations" }, +] + +[[package]] +name = "django-parler" +version = "2.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/2b/2423d31620efe8ab0d0390e60afab4f9cc2e62d4bf39fe0e05df0eef1b93/django-parler-2.3.tar.gz", hash = "sha256:2c8f5012ceb5e49af93b16ea3fe4d0c83d70b91b2d0f470c05d7d742b6f3083d", size = 69167, upload-time = "2021-11-18T09:32:28.959Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/38/11f1a7e3d56f3a6b74cf99e307f2554b741cadebc9b1c45b05e2ec1f35a2/django_parler-2.3-py3-none-any.whl", hash = "sha256:8f6c8061e4b5690f1ee2d8e5760940ef06bf78a5bfa033d11178377559c749cf", size = 83288, upload-time = "2021-11-18T09:32:27.193Z" }, +] + +[[package]] +name = "django-redis" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "redis" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/53/dbcfa1e528e0d6c39947092625b2c89274b5d88f14d357cee53c4d6dbbd4/django_redis-6.0.0.tar.gz", hash = "sha256:2d9cb12a20424a4c4dde082c6122f486628bae2d9c2bee4c0126a4de7fda00dd", size = 56904, upload-time = "2025-06-17T18:15:46.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/79/055dfcc508cfe9f439d9f453741188d633efa9eab90fc78a67b0ab50b137/django_redis-6.0.0-py3-none-any.whl", hash = "sha256:20bf0063a8abee567eb5f77f375143c32810c8700c0674ced34737f8de4e36c0", size = 33687, upload-time = "2025-06-17T18:15:34.165Z" }, +] + +[[package]] +name = "django-timezone-field" +version = "7.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/05/9b93a66452cdb8a08ab26f08d5766d2332673e659a8b2aeb73f2a904d421/django_timezone_field-7.2.1.tar.gz", hash = "sha256:def846f9e7200b7b8f2a28fcce2b78fb2d470f6a9f272b07c4e014f6ba4c6d2e", size = 13096, upload-time = "2025-12-06T23:50:44.591Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/7f/d885667401515b467f84569c56075bc9add72c9fd425fca51a25f4c997e1/django_timezone_field-7.2.1-py3-none-any.whl", hash = "sha256:276915b72c5816f57c3baf9e43f816c695ef940d1b21f91ebf6203c09bf4ad44", size = 13284, upload-time = "2025-12-06T23:50:43.302Z" }, +] + +[[package]] +name = "djangorestframework" +version = "3.16.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/95/5376fe618646fde6899b3cdc85fd959716bb67542e273a76a80d9f326f27/djangorestframework-3.16.1.tar.gz", hash = "sha256:166809528b1aced0a17dc66c24492af18049f2c9420dbd0be29422029cfc3ff7", size = 1089735, upload-time = "2025-08-06T17:50:53.251Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/ce/bf8b9d3f415be4ac5588545b5fcdbbb841977db1c1d923f7568eeabe1689/djangorestframework-3.16.1-py3-none-any.whl", hash = "sha256:33a59f47fb9c85ede792cbf88bde71893bcda0667bc573f784649521f1102cec", size = 1080442, upload-time = "2025-08-06T17:50:50.667Z" }, +] + +[[package]] +name = "djangorestframework-api-key" +version = "3.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/d9/d187626f67eec3d8c7fb170009ffc323e70553dbac8832ca051f4c7e0a53/djangorestframework_api_key-3.1.0.tar.gz", hash = "sha256:7e9c88360933b3c46467d80645a50cf36697674c7856a737a1c674d570860ac9", size = 36922, upload-time = "2025-04-04T08:53:19.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/50/29fd576a9162ff3fcd0423ae5a30e7f9610a438329dd20081a60c758f100/djangorestframework_api_key-3.1.0-py3-none-any.whl", hash = "sha256:1b6ed7d89308cf872b29084cf68f9b7171f7efd2b8f84f480c09aa4232f910c1", size = 15664, upload-time = "2025-04-04T08:53:18.228Z" }, +] + +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + +[[package]] +name = "drf-spectacular" +version = "0.29.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "djangorestframework" }, + { name = "inflection" }, + { name = "jsonschema" }, + { name = "pyyaml" }, + { name = "uritemplate" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/0e/a4f50d83e76cbe797eda88fc0083c8ca970cfa362b5586359ef06ec6f70a/drf_spectacular-0.29.0.tar.gz", hash = "sha256:0a069339ea390ce7f14a75e8b5af4a0860a46e833fd4af027411a3e94fc1a0cc", size = 241722, upload-time = "2025-11-02T03:40:26.348Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d9/502c56fc3ca960075d00956283f1c44e8cafe433dada03f9ed2821f3073b/drf_spectacular-0.29.0-py3-none-any.whl", hash = "sha256:d1ee7c9535d89848affb4427347f7c4a22c5d22530b8842ef133d7b72e19b41a", size = 105433, upload-time = "2025-11-02T03:40:24.823Z" }, +] + +[[package]] +name = "drf-spectacular-sidecar" +version = "2025.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5d/9a/5f1a83bd7bb1937a6347e148fbd116195abb16f7179f7c1b34b3ad2befd8/drf_spectacular_sidecar-2025.12.1.tar.gz", hash = "sha256:d25d82ea2e6176ce4583812f73ac9f177dcd56141c11a9e9bf35f1b1878d5044", size = 2460914, upload-time = "2025-12-01T11:26:59.798Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/03/0c6d70dcf24c4af0648bd0e8543fb9ad6c1952d9dcf01df729e4f4458d4c/drf_spectacular_sidecar-2025.12.1-py3-none-any.whl", hash = "sha256:dd28870327b92a0e3c9b6809147fd3e74ec449176daeae291af34eda176236c1", size = 2482183, upload-time = "2025-12-01T11:26:58.176Z" }, +] + +[[package]] +name = "drf-standardized-errors" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "djangorestframework" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ea/5d/9301be05081261cebdc000f9fbad51dc2b2732f9decd8da693f7c2daae29/drf_standardized_errors-0.15.0.tar.gz", hash = "sha256:83112d072e751eb444c2f16ab4618273b912cffc07f12b81998060fdfa2eb655", size = 60729, upload-time = "2025-06-09T07:47:56.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/94/4e7721ff51cb10aa826cb27f3bf015e8d94d7f898c19c2b650d822019e5b/drf_standardized_errors-0.15.0-py3-none-any.whl", hash = "sha256:75dcfec11433a16c81f8c5948a5cd2932cd5b02f426f64ca82020a78c155b263", size = 25673, upload-time = "2025-06-09T07:47:55.042Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, +] + +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "factory-boy" +version = "3.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "faker" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/98/75cacae9945f67cfe323829fc2ac451f64517a8a330b572a06a323997065/factory_boy-3.3.3.tar.gz", hash = "sha256:866862d226128dfac7f2b4160287e899daf54f2612778327dd03d0e2cb1e3d03", size = 164146, upload-time = "2025-02-03T09:49:04.433Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/8d/2bc5f5546ff2ccb3f7de06742853483ab75bf74f36a92254702f8baecc79/factory_boy-3.3.3-py2.py3-none-any.whl", hash = "sha256:1c39e3289f7e667c4285433f305f8d506efc2fe9c73aaea4151ebd5cdea394fc", size = 37036, upload-time = "2025-02-03T09:49:01.659Z" }, +] + +[[package]] +name = "faker" +version = "39.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/b9/0897fb5888ddda099dc0f314a8a9afb5faa7e52eaf6865c00686dfb394db/faker-39.0.0.tar.gz", hash = "sha256:ddae46d3b27e01cea7894651d687b33bcbe19a45ef044042c721ceac6d3da0ff", size = 1941757, upload-time = "2025-12-17T19:19:04.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/5a/26cdb1b10a55ac6eb11a738cea14865fa753606c4897d7be0f5dc230df00/faker-39.0.0-py3-none-any.whl", hash = "sha256:c72f1fca8f1a24b8da10fcaa45739135a19772218ddd61b86b7ea1b8c790dce7", size = 1980775, upload-time = "2025-12-17T19:19:02.926Z" }, +] + +[[package]] +name = "freezegun" +version = "1.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/dd/23e2f4e357f8fd3bdff613c1fe4466d21bfb00a6177f238079b17f7b1c84/freezegun-1.5.5.tar.gz", hash = "sha256:ac7742a6cc6c25a2c35e9292dfd554b897b517d2dec26891a2e8debf205cb94a", size = 35914, upload-time = "2025-08-09T10:39:08.338Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/2e/b41d8a1a917d6581fc27a35d05561037b048e47df50f27f8ac9c7e27a710/freezegun-1.5.5-py3-none-any.whl", hash = "sha256:cd557f4a75cf074e84bc374249b9dd491eaeacd61376b9eb3c423282211619d2", size = 19266, upload-time = "2025-08-09T10:39:06.636Z" }, +] + +[[package]] +name = "gunicorn" +version = "23.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/72/9614c465dc206155d93eff0ca20d42e1e35afc533971379482de953521a4/gunicorn-23.0.0.tar.gz", hash = "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec", size = 375031, upload-time = "2024-08-10T20:25:27.378Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/7d/6dac2a6e1eba33ee43f318edbed4ff29151a49b5d37f080aad1e6469bca4/gunicorn-23.0.0-py3-none-any.whl", hash = "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", size = 85029, upload-time = "2024-08-10T20:25:24.996Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "icalendar" +version = "6.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5d/70/458092b3e7c15783423fe64d07e63ea3311a597e723be6a1060513e3db93/icalendar-6.3.2.tar.gz", hash = "sha256:e0c10ecbfcebe958d33af7d491f6e6b7580d11d475f2eeb29532d0424f9110a1", size = 178422, upload-time = "2025-11-05T12:49:32.286Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/ee/2ff96bb5bd88fe03ab90aedf5180f96dc0f3ae4648ca264b473055bcaaff/icalendar-6.3.2-py3-none-any.whl", hash = "sha256:d400e9c9bb8c025e5a3c77c236941bb690494be52528a0b43cc7e8b7c9505064", size = 242403, upload-time = "2025-11-05T12:49:30.691Z" }, +] + +[[package]] +name = "icalendar-searcher" +version = "1.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "icalendar" }, + { name = "recurring-ical-events" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/e7/00c6ac3f10689515efb2cf1ab620f18c51c4c110796d6075a6d3ba5b82e2/icalendar_searcher-1.0.3.tar.gz", hash = "sha256:fd43f59ad7ceaf7c86b0fe4cdf261097e68b5c16a82c9892241bdcc0abc7a1d0", size = 35811, upload-time = "2025-11-30T19:19:21.767Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/80/4c88e4048b7d37f85e6b152da9327beb304562a27b7d2edc8c8550adf336/icalendar_searcher-1.0.3-py3-none-any.whl", hash = "sha256:66ab6d95a07039eb2d5f51821f6f0a981b97f43eaf16ff9c6835d6ae3ddd045b", size = 36093, upload-time = "2025-11-30T19:19:20.284Z" }, +] + +[[package]] +name = "icdiff" +version = "2.0.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/e4/43341832be5f2bcae71eb3ef08a07aaef9b74f74fe0b3675f62bd12057fe/icdiff-2.0.7.tar.gz", hash = "sha256:f79a318891adbf59a45e3a7694f5e1f18c5407065264637072ac8363b759866f", size = 16394, upload-time = "2023-08-21T15:00:55.742Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/2a/b3178baa75a3ec75a33588252296c82a1332d2b83cd01061539b74bde9dd/icdiff-2.0.7-py3-none-any.whl", hash = "sha256:f05d1b3623223dd1c70f7848da7d699de3d9a2550b902a8234d9026292fb5762", size = 17018, upload-time = "2023-08-21T15:00:54.634Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "inflection" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/7e/691d061b7329bc8d54edbf0ec22fbfb2afe61facb681f9aaa9bff7a27d04/inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", size = 15091, upload-time = "2020-08-22T08:16:29.139Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/91/aa6bde563e0085a02a435aa99b49ef75b0a4b062635e606dab23ce18d720/inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2", size = 9454, upload-time = "2020-08-22T08:16:27.816Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "ipdb" +version = "0.13.13" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "decorator" }, + { name = "ipython" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/1b/7e07e7b752017f7693a0f4d41c13e5ca29ce8cbcfdcc1fd6c4ad8c0a27a0/ipdb-0.13.13.tar.gz", hash = "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726", size = 17042, upload-time = "2023-03-09T15:40:57.487Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/4c/b075da0092003d9a55cf2ecc1cae9384a1ca4f650d51b00fc59875fe76f6/ipdb-0.13.13-py3-none-any.whl", hash = "sha256:45529994741c4ab6d2388bfa5d7b725c2cf7fe9deffabdb8a6113aa5ed449ed4", size = 12130, upload-time = "2023-03-09T15:40:55.021Z" }, +] + +[[package]] +name = "ipython" +version = "9.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/29/e6/48c74d54039241a456add616464ea28c6ebf782e4110d419411b83dae06f/ipython-9.7.0.tar.gz", hash = "sha256:5f6de88c905a566c6a9d6c400a8fed54a638e1f7543d17aae2551133216b1e4e", size = 4422115, upload-time = "2025-11-05T12:18:54.646Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/aa/62893d6a591d337aa59dcc4c6f6c842f1fe20cd72c8c5c1f980255243252/ipython-9.7.0-py3-none-any.whl", hash = "sha256:bce8ac85eb9521adc94e1845b4c03d88365fd6ac2f4908ec4ed1eb1b0a065f9f", size = 618911, upload-time = "2025-11-05T12:18:52.484Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "isort" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/82/fa43935523efdfcce6abbae9da7f372b627b27142c3419fcf13bf5b0c397/isort-6.1.0.tar.gz", hash = "sha256:9b8f96a14cfee0677e78e941ff62f03769a06d412aabb9e2a90487b3b7e8d481", size = 824325, upload-time = "2025-10-01T16:26:45.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/cc/9b681a170efab4868a032631dea1e8446d8ec718a7f657b94d49d1a12643/isort-6.1.0-py3-none-any.whl", hash = "sha256:58d8927ecce74e5087aef019f778d4081a3b6c98f15a80ba35782ca8a2097784", size = 94329, upload-time = "2025-10-01T16:26:43.291Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jh2" +version = "5.0.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/ed/466eb2a162d9cfaa8452e9a05d24b4fc11d4cf84cf27f5a71457dc590323/jh2-5.0.10.tar.gz", hash = "sha256:2c737a47bee50dc727f7a766185e110befdceba5efb1c4fa240b1e4399291487", size = 7301475, upload-time = "2025-10-05T06:18:59.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/88/91e402bd0e323f3c7895d8eb6e79efe7d94bf40e035f6abcd9da0a08325c/jh2-5.0.10-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5a6885a315bdd24d822873d5e581eac90ab25589fb48d34f822352710139439a", size = 603894, upload-time = "2025-10-05T06:16:22.199Z" }, + { url = "https://files.pythonhosted.org/packages/3e/52/cdf454b01bdf7432848f7576b6054826fc65d77062324164995ff77a813d/jh2-5.0.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa031e2aba9bd4cf6e1c0514764781b907557484cf163f02f1ad65a5932faf2", size = 378697, upload-time = "2025-10-05T06:16:24.128Z" }, + { url = "https://files.pythonhosted.org/packages/8e/dd/6e7106bc020e9fc13a70476c95cd4b40d2d301ef1c5ff7cd093adeec2143/jh2-5.0.10-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c816cfe85ae5d4fb26efc2713aedf9dfe1bb826544fe76cfd35ce7a60e099e8f", size = 390293, upload-time = "2025-10-05T06:16:25.723Z" }, + { url = "https://files.pythonhosted.org/packages/88/94/e64d83f8d2f5b7490e32d12f0ba3835b45b19d14af72ea592aacfb65592e/jh2-5.0.10-cp313-cp313t-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b28c70b440f32bb8f14c3adaa11c094ea109fc1d2540434a8fc6e08cf4cf1aef", size = 524781, upload-time = "2025-10-05T06:16:27.382Z" }, + { url = "https://files.pythonhosted.org/packages/25/72/a2c72aff206bc27f3373982d318f305d31aca62dd5daa0c4e50c528208bb/jh2-5.0.10-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:df79bdf69d33ec0093c63abb633a6cbdb4b905a5ea3dda2514c4adf7e5713d20", size = 518173, upload-time = "2025-10-05T06:16:29.029Z" }, + { url = "https://files.pythonhosted.org/packages/26/27/e41b23fa62a0bbbf87cefdecbd938056a44b9c47a454a11edd760b92a9b3/jh2-5.0.10-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c0b7cda4b50692e2f259382fc2a374cd9118a96f8d369ef04fe088124f84fc", size = 409290, upload-time = "2025-10-05T06:16:30.628Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ed/516bdea8ff60bb321b92bac7d3b99a8aee322495e8b4dccc5b42eeede0b7/jh2-5.0.10-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ffeb6a352ce6c89d77bd185972185f20e3c35b3be4d0253963b6d8b6444c4aa", size = 386155, upload-time = "2025-10-05T06:16:31.898Z" }, + { url = "https://files.pythonhosted.org/packages/12/18/057408a548a66eb069c2fa12bfd13c1e34eaae07603f40ce32743ce0faa6/jh2-5.0.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:271720035a1293031c807e24a27235a2426c51de8755db872eb1adad310213cd", size = 403861, upload-time = "2025-10-05T06:16:33.036Z" }, + { url = "https://files.pythonhosted.org/packages/3d/70/73d22e62af0e756cb3b86ee57b67b117efe75091d56ff286bf136adde863/jh2-5.0.10-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:7b28fc12106654573881f19b1a78e41cf37657ae76efa84e7da518faced56f0f", size = 559909, upload-time = "2025-10-05T06:16:34.262Z" }, + { url = "https://files.pythonhosted.org/packages/66/fa/5d5e4304ecfa27773bbe036454b782882fc2ab02f7521ae0d367514c7618/jh2-5.0.10-cp313-cp313t-musllinux_1_1_armv7l.whl", hash = "sha256:976134b61b7fdf290a7cc70e7676c2605af84dd83e2a1e78c170928a0119278b", size = 653300, upload-time = "2025-10-05T06:16:35.825Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b4/31583a8bcbe58ee13b30bdf9d82ca52a3272a13c45384bf8e193a2e4541f/jh2-5.0.10-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:75581b5acbcc344e070f811938919165999bf7221406845306e0ab860605cdbf", size = 580061, upload-time = "2025-10-05T06:16:37.598Z" }, + { url = "https://files.pythonhosted.org/packages/66/3e/ffcc082b72c7f83512cc1dbda866afa5c0dbd76c423e6f0294496744af27/jh2-5.0.10-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:206e4a92c687f6928b3846d7666ebf2602c16556feb154f16f1d399219046f5d", size = 550849, upload-time = "2025-10-05T06:16:38.887Z" }, + { url = "https://files.pythonhosted.org/packages/19/da/01f0df3a779d0d2e8b7ce121da48b1a91346264fd494c0be16a74e5c1c4f/jh2-5.0.10-cp313-cp313t-win32.whl", hash = "sha256:fca31a36827205c76c959be94e8bad7aaa1be06ea8ed904b20b5d96a7829ce45", size = 234414, upload-time = "2025-10-05T06:16:40.509Z" }, + { url = "https://files.pythonhosted.org/packages/82/c1/42a68cbe4c6ee9453d3685bd4ebce8e3bccbda608b3c26f380cf30640825/jh2-5.0.10-cp313-cp313t-win_amd64.whl", hash = "sha256:4bbefb69efaa365f3193d0db096d34e9e0da5885b0bb1341ab7593852e811f69", size = 241768, upload-time = "2025-10-05T06:16:41.701Z" }, + { url = "https://files.pythonhosted.org/packages/10/14/4d89e958e2a98ee09895290a105caee5cd158fb456fc9aae913f15251184/jh2-5.0.10-cp313-cp313t-win_arm64.whl", hash = "sha256:9752ea045ab3da4544104201a800d3f7ce7c63b529db5a9715c587cbfedca9b7", size = 237090, upload-time = "2025-10-05T06:16:43.228Z" }, + { url = "https://files.pythonhosted.org/packages/63/8f/fe337b9104ab3a444a7b20baffc3dd54f3227a44f3037aba2a30bf36fefd/jh2-5.0.10-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7c2918379cce3352b6d40717ed3d5b06da6e6c17253317302cab2f0dbff62a5d", size = 622842, upload-time = "2025-10-05T06:17:06.121Z" }, + { url = "https://files.pythonhosted.org/packages/63/37/f3c59f62e771755b31b6d1ce9124d4ab40bc3a2206116bfd879a33c1b02f/jh2-5.0.10-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd229bbe7dfdf499394fa8453c92e2ea19de47c80afc1efaec7f85704be97717", size = 385674, upload-time = "2025-10-05T06:17:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/03/9d/719cfd3afab6bb9115f574687fa24ea5731267ee9701439e30e06a45f468/jh2-5.0.10-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:36e9b5fb9cd8872846d031fae442df1b5c83f4dd29ef1dd1c3f70afd86fe8fc3", size = 396276, upload-time = "2025-10-05T06:17:08.933Z" }, + { url = "https://files.pythonhosted.org/packages/22/63/1f36ff610684f2cb177218c700d3a3f4f87aad4d45a6e3f59feb360812c6/jh2-5.0.10-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:217af8256551627b9253737a866c05ce5f6c49f171c099260b76915239cfb13a", size = 532742, upload-time = "2025-10-05T06:17:10.396Z" }, + { url = "https://files.pythonhosted.org/packages/59/c5/063fe0b930c0b15e8c0376d9d6cc20dcc3179823e6f456c1a571db1d27c4/jh2-5.0.10-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e20e3d747c4022d890865fb25f2e8b3ff6cbacf7556f29155dcfbff592d96202", size = 525320, upload-time = "2025-10-05T06:17:12.187Z" }, + { url = "https://files.pythonhosted.org/packages/e8/7a/c1f4a961554f6b521bfc75320264c0bde50210c11a206719e0c98c17e617/jh2-5.0.10-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ea77b8b6b7defb67cbec69340e653495b36881671e9f0ac395cdd6b27144000", size = 416184, upload-time = "2025-10-05T06:17:13.428Z" }, + { url = "https://files.pythonhosted.org/packages/37/c9/75fdfd2ef673accba9b1ace28ffa2aaced23fba3209ac73521e441ae2265/jh2-5.0.10-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fd6b5b2d4d38e089ac982ea341b36f2cb827c0765217e6b8f3e58a409290e6f", size = 394145, upload-time = "2025-10-05T06:17:14.673Z" }, + { url = "https://files.pythonhosted.org/packages/52/5e/38b1b14182afcebf89d542b7a2e4cd4d7deaf9e4cae0a45b0a85115f0da7/jh2-5.0.10-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c3d38121a1ddc2ffc769f09aaaa4c7e67f89e25c578921326b515402176e7cf", size = 411333, upload-time = "2025-10-05T06:17:15.913Z" }, + { url = "https://files.pythonhosted.org/packages/a8/04/10383a467f24d2643013f784bca4ddb81dc9d0d81641a846b71bd0aa64e0/jh2-5.0.10-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:33e4ac058acf8f3f89ea1375deb33ac61713d60fb9e3333bd079f3602425739c", size = 565892, upload-time = "2025-10-05T06:17:17.517Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1a/b416bd65176593b405320bfd763ddc9cae3941fe96c7055ec1c46e081ebd/jh2-5.0.10-cp37-abi3-musllinux_1_1_armv7l.whl", hash = "sha256:86571f18274d7a5a7e6406e156a9f27fa1a72203a176921ea234c4a11fe0e105", size = 659878, upload-time = "2025-10-05T06:17:18.972Z" }, + { url = "https://files.pythonhosted.org/packages/a9/2d/e4c3b90585e92676777e9bcb9218ce97552f0c9797cec142d549904ca67b/jh2-5.0.10-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:62f0842b5f8da463b6a548a8c2a7e69fa709888d03c997486390097341e88e09", size = 587129, upload-time = "2025-10-05T06:17:20.669Z" }, + { url = "https://files.pythonhosted.org/packages/98/d5/3e89d65bb6bbcdaa14236e9ec8f643cf77a5809d7315ce1208f0ef53927c/jh2-5.0.10-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f3b6401f089a65b87f2e5beffe81666a1c2ab1d90e8406cd49c756d66881bedc", size = 556811, upload-time = "2025-10-05T06:17:22.37Z" }, + { url = "https://files.pythonhosted.org/packages/7d/8c/a05403065463ef759059d75e0862c94aa60d2019a7dcd41d716f6d8d6c32/jh2-5.0.10-cp37-abi3-win32.whl", hash = "sha256:7b79771bd366a11a36041f49cabc7876047cf1b99cee89df1333e6890f66d973", size = 239474, upload-time = "2025-10-05T06:17:23.637Z" }, + { url = "https://files.pythonhosted.org/packages/96/ac/92f97f07f748bdc9280c5d50e787773bef188c29c32f6804f2fc72cca725/jh2-5.0.10-cp37-abi3-win_amd64.whl", hash = "sha256:9c730e3f40f22bd4ff0ab63ee41d70ee22aa1cc54e5cb295ae0ac3b0a016af3e", size = 246320, upload-time = "2025-10-05T06:17:25.313Z" }, + { url = "https://files.pythonhosted.org/packages/f0/ad/e9f4035ddd847efe26914da64f9d54198bf5b0bdcfd0e8bbcf6a328e1f7c/jh2-5.0.10-cp37-abi3-win_arm64.whl", hash = "sha256:d18eccec757374afca8de31bf012a888fb82903d5803e84f2e6f0b707478ced6", size = 241790, upload-time = "2025-10-05T06:17:26.488Z" }, + { url = "https://files.pythonhosted.org/packages/93/57/d0fcb025736e24cb68c4e250cc4cf63a87b7e0bd7285e188c543018d05c1/jh2-5.0.10-py3-none-any.whl", hash = "sha256:1808c0e5d355c60485bb282b34c6aa3f15069b2634eb44779fb9f3bda0256ac0", size = 98099, upload-time = "2025-10-05T06:18:58.203Z" }, +] + +[[package]] +name = "josepy" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/ad/6f520aee9cc9618d33430380741e9ef859b2c560b1e7915e755c084f6bc0/josepy-2.2.0.tar.gz", hash = "sha256:74c033151337c854f83efe5305a291686cef723b4b970c43cfe7270cf4a677a9", size = 56500, upload-time = "2025-10-14T14:54:42.108Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/b2/b5caed897fbb1cc286c62c01feca977e08d99a17230ff3055b9a98eccf1d/josepy-2.2.0-py3-none-any.whl", hash = "sha256:63e9dd116d4078778c25ca88f880cc5d95f1cab0099bebe3a34c2e299f65d10b", size = 29211, upload-time = "2025-10-14T14:54:41.144Z" }, +] + +[[package]] +name = "joserfc" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/a0/e77842f16d07ef8d23faf9cf675f2f5b358b093253b41b53f6214a52e5e7/joserfc-1.6.0.tar.gz", hash = "sha256:27946ee53f591c2da65b726a663a68f0fb000732eaadfe819bbbda6429702ad0", size = 225982, upload-time = "2025-12-14T05:20:38.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ac/2b/94a31afef483ea5ac05c3545defed42704e941713dff5d9dbe5212ad5452/joserfc-1.6.0-py3-none-any.whl", hash = "sha256:14ed0d9cef03aa9332452cbcc59ff31c8c7b3f9737401a9ead3009c2a914bf54", size = 70259, upload-time = "2025-12-14T05:20:37.238Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.25.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "kombu" +version = "5.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "amqp" }, + { name = "packaging" }, + { name = "tzdata" }, + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/05/749ada8e51718445d915af13f1d18bc4333848e8faa0cb234028a3328ec8/kombu-5.6.1.tar.gz", hash = "sha256:90f1febb57ad4f53ca327a87598191b2520e0c793c75ea3b88d98e3b111282e4", size = 471548, upload-time = "2025-11-25T11:07:33.504Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/d6/943cf84117cd9ddecf6e1707a3f712a49fc64abdb8ac31b19132871af1dd/kombu-5.6.1-py3-none-any.whl", hash = "sha256:b69e3f5527ec32fc5196028a36376501682973e9620d6175d1c3d4eaf7e95409", size = 214141, upload-time = "2025-11-25T11:07:31.54Z" }, +] + +[package.optional-dependencies] +redis = [ + { name = "redis" }, +] + +[[package]] +name = "lxml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/88/262177de60548e5a2bfc46ad28232c9e9cbde697bd94132aeb80364675cb/lxml-6.0.2.tar.gz", hash = "sha256:cd79f3367bd74b317dda655dc8fcfa304d9eb6e4fb06b7168c5cf27f96e0cd62", size = 4073426, upload-time = "2025-09-22T04:04:59.287Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/53/fd/4e8f0540608977aea078bf6d79f128e0e2c2bba8af1acf775c30baa70460/lxml-6.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9b33d21594afab46f37ae58dfadd06636f154923c4e8a4d754b0127554eb2e77", size = 8648494, upload-time = "2025-09-22T04:01:54.242Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f4/2a94a3d3dfd6c6b433501b8d470a1960a20ecce93245cf2db1706adf6c19/lxml-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6c8963287d7a4c5c9a432ff487c52e9c5618667179c18a204bdedb27310f022f", size = 4661146, upload-time = "2025-09-22T04:01:56.282Z" }, + { url = "https://files.pythonhosted.org/packages/25/2e/4efa677fa6b322013035d38016f6ae859d06cac67437ca7dc708a6af7028/lxml-6.0.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1941354d92699fb5ffe6ed7b32f9649e43c2feb4b97205f75866f7d21aa91452", size = 4946932, upload-time = "2025-09-22T04:01:58.989Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0f/526e78a6d38d109fdbaa5049c62e1d32fdd70c75fb61c4eadf3045d3d124/lxml-6.0.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bb2f6ca0ae2d983ded09357b84af659c954722bbf04dea98030064996d156048", size = 5100060, upload-time = "2025-09-22T04:02:00.812Z" }, + { url = "https://files.pythonhosted.org/packages/81/76/99de58d81fa702cc0ea7edae4f4640416c2062813a00ff24bd70ac1d9c9b/lxml-6.0.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eb2a12d704f180a902d7fa778c6d71f36ceb7b0d317f34cdc76a5d05aa1dd1df", size = 5019000, upload-time = "2025-09-22T04:02:02.671Z" }, + { url = "https://files.pythonhosted.org/packages/b5/35/9e57d25482bc9a9882cb0037fdb9cc18f4b79d85df94fa9d2a89562f1d25/lxml-6.0.2-cp313-cp313-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:6ec0e3f745021bfed19c456647f0298d60a24c9ff86d9d051f52b509663feeb1", size = 5348496, upload-time = "2025-09-22T04:02:04.904Z" }, + { url = "https://files.pythonhosted.org/packages/a6/8e/cb99bd0b83ccc3e8f0f528e9aa1f7a9965dfec08c617070c5db8d63a87ce/lxml-6.0.2-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:846ae9a12d54e368933b9759052d6206a9e8b250291109c48e350c1f1f49d916", size = 5643779, upload-time = "2025-09-22T04:02:06.689Z" }, + { url = "https://files.pythonhosted.org/packages/d0/34/9e591954939276bb679b73773836c6684c22e56d05980e31d52a9a8deb18/lxml-6.0.2-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9266d2aa545d7374938fb5c484531ef5a2ec7f2d573e62f8ce722c735685fd", size = 5244072, upload-time = "2025-09-22T04:02:08.587Z" }, + { url = "https://files.pythonhosted.org/packages/8d/27/b29ff065f9aaca443ee377aff699714fcbffb371b4fce5ac4ca759e436d5/lxml-6.0.2-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:4077b7c79f31755df33b795dc12119cb557a0106bfdab0d2c2d97bd3cf3dffa6", size = 4718675, upload-time = "2025-09-22T04:02:10.783Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f756f9c2cd27caa1a6ef8c32ae47aadea697f5c2c6d07b0dae133c244fbe/lxml-6.0.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a7c5d5e5f1081955358533be077166ee97ed2571d6a66bdba6ec2f609a715d1a", size = 5255171, upload-time = "2025-09-22T04:02:12.631Z" }, + { url = "https://files.pythonhosted.org/packages/61/46/bb85ea42d2cb1bd8395484fd72f38e3389611aa496ac7772da9205bbda0e/lxml-6.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8f8d0cbd0674ee89863a523e6994ac25fd5be9c8486acfc3e5ccea679bad2679", size = 5057175, upload-time = "2025-09-22T04:02:14.718Z" }, + { url = "https://files.pythonhosted.org/packages/95/0c/443fc476dcc8e41577f0af70458c50fe299a97bb6b7505bb1ae09aa7f9ac/lxml-6.0.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2cbcbf6d6e924c28f04a43f3b6f6e272312a090f269eff68a2982e13e5d57659", size = 4785688, upload-time = "2025-09-22T04:02:16.957Z" }, + { url = "https://files.pythonhosted.org/packages/48/78/6ef0b359d45bb9697bc5a626e1992fa5d27aa3f8004b137b2314793b50a0/lxml-6.0.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dfb874cfa53340009af6bdd7e54ebc0d21012a60a4e65d927c2e477112e63484", size = 5660655, upload-time = "2025-09-22T04:02:18.815Z" }, + { url = "https://files.pythonhosted.org/packages/ff/ea/e1d33808f386bc1339d08c0dcada6e4712d4ed8e93fcad5f057070b7988a/lxml-6.0.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb8dae0b6b8b7f9e96c26fdd8121522ce5de9bb5538010870bd538683d30e9a2", size = 5247695, upload-time = "2025-09-22T04:02:20.593Z" }, + { url = "https://files.pythonhosted.org/packages/4f/47/eba75dfd8183673725255247a603b4ad606f4ae657b60c6c145b381697da/lxml-6.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:358d9adae670b63e95bc59747c72f4dc97c9ec58881d4627fe0120da0f90d314", size = 5269841, upload-time = "2025-09-22T04:02:22.489Z" }, + { url = "https://files.pythonhosted.org/packages/76/04/5c5e2b8577bc936e219becb2e98cdb1aca14a4921a12995b9d0c523502ae/lxml-6.0.2-cp313-cp313-win32.whl", hash = "sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2", size = 3610700, upload-time = "2025-09-22T04:02:24.465Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0a/4643ccc6bb8b143e9f9640aa54e38255f9d3b45feb2cbe7ae2ca47e8782e/lxml-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7", size = 4010347, upload-time = "2025-09-22T04:02:26.286Z" }, + { url = "https://files.pythonhosted.org/packages/31/ef/dcf1d29c3f530577f61e5fe2f1bd72929acf779953668a8a47a479ae6f26/lxml-6.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf", size = 3671248, upload-time = "2025-09-22T04:02:27.918Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "mozilla-django-oidc" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "django" }, + { name = "josepy" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/90/f9/1ca554a62bf8a4fd31b68209df8603075c2b7436400ea3f7ddd597f204a5/mozilla-django-oidc-4.0.1.tar.gz", hash = "sha256:4ff8c64069e3e05c539cecf9345e73225a99641a25e13b7a5f933ec897b58918", size = 49027, upload-time = "2024-03-12T12:29:26.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d6/2b75bf4e742c54028ae07a1fb5a2624e5a73e9cfd2185c2df0e22cbfe14e/mozilla_django_oidc-4.0.1-py2.py3-none-any.whl", hash = "sha256:04ef58759be69f22cdc402d082480aaebf193466cad385dc9e4f8df2a0b187ca", size = 29059, upload-time = "2024-03-12T12:29:24.978Z" }, +] + +[[package]] +name = "nested-multipart-parser" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/48/b91a6f924a2abd9e86b501347ca56989e2c2b4bf3eac86bff57f80b99b75/nested_multipart_parser-1.6.0.tar.gz", hash = "sha256:8c7a07952a4a3c2cb2b99ca16158961af215c6f8c9e04337bc13da016500c69c", size = 13159, upload-time = "2025-09-17T20:47:25.627Z" } + +[[package]] +name = "niquests" +version = "3.16.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "charset-normalizer" }, + { name = "urllib3-future" }, + { name = "wassima" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/95/39d0917de33ce1ebec27fa00660df9faad7608de14eaf7fc3bf43d84d3c4/niquests-3.16.1.tar.gz", hash = "sha256:0750eb7fb4bdf46af5041e75c5f37a2a6974e6f620b0f6a234c4b858dbf38ddb", size = 981092, upload-time = "2025-12-23T16:42:09.548Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/c5/0d136dac4051352da613e8676743dad21d41578832d622d3b4db7a103967/niquests-3.16.1-py3-none-any.whl", hash = "sha256:e26e302f36fb6730f9c36755506a84a5f2bb1ae92c7ef5029a6cc7cf98622ded", size = 170850, upload-time = "2025-12-23T16:42:08.072Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "parso" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "pillow" +version = "12.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/cace85a1b0c9775a9f8f5d5423c8261c858760e2466c79b2dd184638b056/pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353", size = 47008828, upload-time = "2025-10-15T18:24:14.008Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/f2/de993bb2d21b33a98d031ecf6a978e4b61da207bef02f7b43093774c480d/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643", size = 4045493, upload-time = "2025-10-15T18:22:25.758Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b6/bc8d0c4c9f6f111a783d045310945deb769b806d7574764234ffd50bc5ea/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4", size = 4120461, upload-time = "2025-10-15T18:22:27.286Z" }, + { url = "https://files.pythonhosted.org/packages/5d/57/d60d343709366a353dc56adb4ee1e7d8a2cc34e3fbc22905f4167cfec119/pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399", size = 3576912, upload-time = "2025-10-15T18:22:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/a0a31467e3f83b94d37568294b01d22b43ae3c5d85f2811769b9c66389dd/pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5", size = 5249132, upload-time = "2025-10-15T18:22:30.641Z" }, + { url = "https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b", size = 4650099, upload-time = "2025-10-15T18:22:32.73Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bd/69ed99fd46a8dba7c1887156d3572fe4484e3f031405fcc5a92e31c04035/pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3", size = 6230808, upload-time = "2025-10-15T18:22:34.337Z" }, + { url = "https://files.pythonhosted.org/packages/ea/94/8fad659bcdbf86ed70099cb60ae40be6acca434bbc8c4c0d4ef356d7e0de/pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07", size = 8037804, upload-time = "2025-10-15T18:22:36.402Z" }, + { url = "https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e", size = 6345553, upload-time = "2025-10-15T18:22:38.066Z" }, + { url = "https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344", size = 7037729, upload-time = "2025-10-15T18:22:39.769Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/7e94f4c41d238615674d06ed677c14883103dce1c52e4af16f000338cfd7/pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27", size = 6459789, upload-time = "2025-10-15T18:22:41.437Z" }, + { url = "https://files.pythonhosted.org/packages/9c/14/4448bb0b5e0f22dd865290536d20ec8a23b64e2d04280b89139f09a36bb6/pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79", size = 7130917, upload-time = "2025-10-15T18:22:43.152Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ca/16c6926cc1c015845745d5c16c9358e24282f1e588237a4c36d2b30f182f/pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098", size = 6302391, upload-time = "2025-10-15T18:22:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/6d/2a/dd43dcfd6dae9b6a49ee28a8eedb98c7d5ff2de94a5d834565164667b97b/pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905", size = 7007477, upload-time = "2025-10-15T18:22:46.838Z" }, + { url = "https://files.pythonhosted.org/packages/77/f0/72ea067f4b5ae5ead653053212af05ce3705807906ba3f3e8f58ddf617e6/pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a", size = 2435918, upload-time = "2025-10-15T18:22:48.399Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5e/9046b423735c21f0487ea6cb5b10f89ea8f8dfbe32576fe052b5ba9d4e5b/pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3", size = 5251406, upload-time = "2025-10-15T18:22:49.905Z" }, + { url = "https://files.pythonhosted.org/packages/12/66/982ceebcdb13c97270ef7a56c3969635b4ee7cd45227fa707c94719229c5/pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced", size = 4653218, upload-time = "2025-10-15T18:22:51.587Z" }, + { url = "https://files.pythonhosted.org/packages/16/b3/81e625524688c31859450119bf12674619429cab3119eec0e30a7a1029cb/pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b", size = 6266564, upload-time = "2025-10-15T18:22:53.215Z" }, + { url = "https://files.pythonhosted.org/packages/98/59/dfb38f2a41240d2408096e1a76c671d0a105a4a8471b1871c6902719450c/pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d", size = 8069260, upload-time = "2025-10-15T18:22:54.933Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3d/378dbea5cd1874b94c312425ca77b0f47776c78e0df2df751b820c8c1d6c/pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a", size = 6379248, upload-time = "2025-10-15T18:22:56.605Z" }, + { url = "https://files.pythonhosted.org/packages/84/b0/d525ef47d71590f1621510327acec75ae58c721dc071b17d8d652ca494d8/pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe", size = 7066043, upload-time = "2025-10-15T18:22:58.53Z" }, + { url = "https://files.pythonhosted.org/packages/61/2c/aced60e9cf9d0cde341d54bf7932c9ffc33ddb4a1595798b3a5150c7ec4e/pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee", size = 6490915, upload-time = "2025-10-15T18:23:00.582Z" }, + { url = "https://files.pythonhosted.org/packages/ef/26/69dcb9b91f4e59f8f34b2332a4a0a951b44f547c4ed39d3e4dcfcff48f89/pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef", size = 7157998, upload-time = "2025-10-15T18:23:02.627Z" }, + { url = "https://files.pythonhosted.org/packages/61/2b/726235842220ca95fa441ddf55dd2382b52ab5b8d9c0596fe6b3f23dafe8/pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9", size = 6306201, upload-time = "2025-10-15T18:23:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/2afaf4e840b2df71344ababf2f8edd75a705ce500e5dc1e7227808312ae1/pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b", size = 7013165, upload-time = "2025-10-15T18:23:06.46Z" }, + { url = "https://files.pythonhosted.org/packages/6f/75/3fa09aa5cf6ed04bee3fa575798ddf1ce0bace8edb47249c798077a81f7f/pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47", size = 2437834, upload-time = "2025-10-15T18:23:08.194Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pprintpp" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/06/1a/7737e7a0774da3c3824d654993cf57adc915cb04660212f03406334d8c0b/pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403", size = 17995, upload-time = "2018-07-01T01:42:34.87Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/d1/e4ed95fdd3ef13b78630280d9e9e240aeb65cc7c544ec57106149c3942fb/pprintpp-0.4.0-py2.py3-none-any.whl", hash = "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d", size = 16952, upload-time = "2018-07-01T01:42:36.496Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psycopg" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/ed/3a30e8ef82d4128c76aa9bd6b2a7fe6c16c283811e6655997f5047801b47/psycopg-3.3.1.tar.gz", hash = "sha256:ccfa30b75874eef809c0fbbb176554a2640cc1735a612accc2e2396a92442fc6", size = 165596, upload-time = "2025-12-02T21:09:55.545Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/f3/0b4a4c25a47c2d907afa97674287dab61bc9941c9ac3972a67100e33894d/psycopg-3.3.1-py3-none-any.whl", hash = "sha256:e44d8eae209752efe46318f36dd0fdf5863e928009338d736843bb1084f6435c", size = 212760, upload-time = "2025-12-02T21:02:36.029Z" }, +] + +[package.optional-dependencies] +binary = [ + { name = "psycopg-binary", marker = "implementation_name != 'pypy'" }, +] + +[[package]] +name = "psycopg-binary" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/44/f907c508267bc203082217faf5750274f4c240471f99990db70ed9f4dada/psycopg_binary-3.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fda22ce8530236381ff79a674ebc319f1a224f2e39a44158774e55e1488f89b9", size = 4579070, upload-time = "2025-12-02T21:08:04.885Z" }, + { url = "https://files.pythonhosted.org/packages/08/61/554bd7b9b93aef79f0bd3c4d381d9809ecf38e55ab4eb5984f58a74695f7/psycopg_binary-3.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d2fc5fa6c45c406e43c8cc2787055d487b3ae597d2139125191b37fa04835f01", size = 4657517, upload-time = "2025-12-02T21:08:08.941Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1b/c3bc20b72b9b056d1f7a3a131d676c66fe2bc7585f9d9f23d659d8725407/psycopg_binary-3.3.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4d97e4d27cc7ee6938faf7dc9919c452581b4795bd97f3f48582846f24ab81ed", size = 5452087, upload-time = "2025-12-02T21:08:15.144Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e6/58ae55874b963893f46d68748b28e05c432b0c109f53b40970ba6bf9fe95/psycopg_binary-3.3.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f4fb5a3cf4373a8b06c2feb8f29ff4c69968ba443687dedec9f79ce22ef339ae", size = 5131126, upload-time = "2025-12-02T21:08:23.463Z" }, + { url = "https://files.pythonhosted.org/packages/4c/28/bfcfb1b7c2907585292aaf61e902cbd00ecff50120178bc3e8268a74c1d6/psycopg_binary-3.3.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4de5298b81423648ae751c789a6adb7f9396bd4de7f402db8f469901d676ebe4", size = 6722913, upload-time = "2025-12-02T21:08:30.328Z" }, + { url = "https://files.pythonhosted.org/packages/c5/ba/7f6d3117059d4824854fb4eeafe7cb9fe069a43724f6a36b21aac0cd911d/psycopg_binary-3.3.1-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a41139976b8546b78ccd776b9f63665c247e209ae384fa6908ea401e9df2c385", size = 4966088, upload-time = "2025-12-02T21:08:34.666Z" }, + { url = "https://files.pythonhosted.org/packages/a5/18/d1baed589d7254be32eda44262787e397d1845fc7f08a30c38bf9345d361/psycopg_binary-3.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8ea017e58fa7fd8df1d9058ff0248e28f29312bf150a00114fc0ace8a800bfa", size = 4493332, upload-time = "2025-12-02T21:08:38.935Z" }, + { url = "https://files.pythonhosted.org/packages/08/62/57c6ac97cd4d1297115c3840fe09a19ae50b96294e3b8e988385497dc074/psycopg_binary-3.3.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:447e31350ea6816af03f39e6fc5ccccf18e34dc223a7d82734621048bb3fb9af", size = 4170782, upload-time = "2025-12-02T21:08:43.949Z" }, + { url = "https://files.pythonhosted.org/packages/12/27/b2577aad1baaa476cf482fb207850fb3f03467b3e6f3485e8cf360588ea8/psycopg_binary-3.3.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:1f97f1814b046c8103b0a46a8c36c28399489716eba70ed38fbae30a27866e2c", size = 3910543, upload-time = "2025-12-02T21:08:48.202Z" }, + { url = "https://files.pythonhosted.org/packages/dc/89/7ad39e369706beda88827031504d9bb5fed58bf6fe50ec7045bd6750736b/psycopg_binary-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3986f783ff656a0392b81b7ac1e0f88a276a38276a5c93c0b89d4862e309d618", size = 4220070, upload-time = "2025-12-02T21:08:52.752Z" }, + { url = "https://files.pythonhosted.org/packages/ad/3a/703c155ab9fb64c874921116fd740c93494e6bd599b1bcd9e4987f5dcfb4/psycopg_binary-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:63e7c689a4249a1303da35df0b813e7cb3b9e2e5eae492a47482ee1a41dc66b2", size = 3540907, upload-time = "2025-12-02T21:08:56.898Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pycparser" +version = "2.23" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, +] + +[[package]] +name = "pyfakefs" +version = "5.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/1c/4b9489847535a41e074d108bfb86119ab463aa3012f4cb8f6b7f9154e00a/pyfakefs-5.10.2.tar.gz", hash = "sha256:8ae0e5421e08de4e433853a4609a06a1835f4bc2a3ce13b54f36713a897474ba", size = 231379, upload-time = "2025-11-04T20:19:04.446Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/65/3a15447a8630a6bb79cf1ecd9e323a72b28830cb9f367494bedcd045059d/pyfakefs-5.10.2-py3-none-any.whl", hash = "sha256:6ff0e84653a71efc6a73f9ee839c3141e3a7cdf4e1fb97666f82ac5b24308d64", size = 246305, upload-time = "2025-11-04T20:19:02.583Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, +] + +[[package]] +name = "pylint" +version = "3.3.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astroid" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "dill" }, + { name = "isort" }, + { name = "mccabe" }, + { name = "platformdirs" }, + { name = "tomlkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/9d/81c84a312d1fa8133b0db0c76148542a98349298a01747ab122f9314b04e/pylint-3.3.9.tar.gz", hash = "sha256:d312737d7b25ccf6b01cc4ac629b5dcd14a0fcf3ec392735ac70f137a9d5f83a", size = 1525946, upload-time = "2025-10-05T18:41:43.786Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/a7/69460c4a6af7575449e615144aa2205b89408dc2969b87bc3df2f262ad0b/pylint-3.3.9-py3-none-any.whl", hash = "sha256:01f9b0462c7730f94786c283f3e52a1fbdf0494bbe0971a78d7277ef46a751e7", size = 523465, upload-time = "2025-10-05T18:41:41.766Z" }, +] + +[[package]] +name = "pylint-django" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pylint" }, + { name = "pylint-plugin-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/d3/42f88e7549c6d69d9642e7f2de7a1a4a3d45fd352a8ca049c554a3feaba0/pylint-django-2.6.1.tar.gz", hash = "sha256:19e8c85a8573a04e3de7be2ba91e9a7c818ebf05e1b617be2bbae67a906b725f", size = 31970, upload-time = "2024-10-10T14:46:37.931Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/82/88b58feecce482e76e4ec4a45e44ed28075fddd82530d071d89466e83529/pylint_django-2.6.1-py3-none-any.whl", hash = "sha256:359f68fe8c810ee6bc8e1ab4c83c19b15a43b234a24b08978f47a23462b5ce28", size = 42858, upload-time = "2024-10-10T14:46:36.236Z" }, +] + +[[package]] +name = "pylint-plugin-utils" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pylint" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/85/24eaf5d0d078fc8799ae6d89faf326d6e4d27d862fc9a710a52ab07b7bb5/pylint_plugin_utils-0.9.0.tar.gz", hash = "sha256:5468d763878a18d5cc4db46eaffdda14313b043c962a263a7d78151b90132055", size = 10474, upload-time = "2025-06-24T07:14:00.534Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/c9/a3b871b0b590c49e38884af6dab58ab9711053bd5c39b8899b72e367b9f6/pylint_plugin_utils-0.9.0-py3-none-any.whl", hash = "sha256:16e9b84e5326ba893a319a0323fcc8b4bcc9c71fc654fcabba0605596c673818", size = 11129, upload-time = "2025-06-24T07:13:58.993Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/56/f013048ac4bc4c1d9be45afd4ab209ea62822fb1598f40687e6bf45dcea4/pytest-9.0.1.tar.gz", hash = "sha256:3e9c069ea73583e255c3b21cf46b8d3c56f6e3a1a8f6da94ccb0fcf57b9d73c8", size = 1564125, upload-time = "2025-11-12T13:05:09.333Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/8b/6300fb80f858cda1c51ffa17075df5d846757081d11ab4aa35cef9e6258b/pytest-9.0.1-py3-none-any.whl", hash = "sha256:67be0030d194df2dfa7b556f2e56fb3c3315bd5c8822c6951162b92b32ce7dad", size = 373668, upload-time = "2025-11-12T13:05:07.379Z" }, +] + +[[package]] +name = "pytest-cov" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage" }, + { name = "pluggy" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, +] + +[[package]] +name = "pytest-django" +version = "4.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/fb/55d580352db26eb3d59ad50c64321ddfe228d3d8ac107db05387a2fadf3a/pytest_django-4.11.1.tar.gz", hash = "sha256:a949141a1ee103cb0e7a20f1451d355f83f5e4a5d07bdd4dcfdd1fd0ff227991", size = 86202, upload-time = "2025-04-03T18:56:09.338Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/ac/bd0608d229ec808e51a21044f3f2f27b9a37e7a0ebaca7247882e67876af/pytest_django-4.11.1-py3-none-any.whl", hash = "sha256:1b63773f648aa3d8541000c26929c1ea63934be1cfa674c76436966d73fe6a10", size = 25281, upload-time = "2025-04-03T18:56:07.678Z" }, +] + +[[package]] +name = "pytest-icdiff" +version = "0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "icdiff" }, + { name = "pprintpp" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/0c/66e1e2590e98f4428e374a3b6448dc086a908d15b1e24b914539d13b7ac4/pytest-icdiff-0.9.tar.gz", hash = "sha256:13aede616202e57fcc882568b64589002ef85438046f012ac30a8d959dac8b75", size = 7110, upload-time = "2023-12-05T11:18:30.192Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/e1/cafe1edf7a30be6fa1bbbf43f7af12b34682eadcf19eb6e9f7352062c422/pytest_icdiff-0.9-py3-none-any.whl", hash = "sha256:efee0da3bd1b24ef2d923751c5c547fbb8df0a46795553fba08ef57c3ca03d82", size = 4994, upload-time = "2023-12-05T11:18:28.572Z" }, +] + +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + +[[package]] +name = "python-crontab" +version = "3.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/99/7f/c54fb7e70b59844526aa4ae321e927a167678660ab51dda979955eafb89a/python_crontab-3.3.0.tar.gz", hash = "sha256:007c8aee68dddf3e04ec4dce0fac124b93bd68be7470fc95d2a9617a15de291b", size = 57626, upload-time = "2025-07-13T20:05:35.535Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/42/bb4afa5b088f64092036221843fc989b7db9d9d302494c1f8b024ee78a46/python_crontab-3.3.0-py3-none-any.whl", hash = "sha256:739a778b1a771379b75654e53fd4df58e5c63a9279a63b5dfe44c0fcc3ee7884", size = 27533, upload-time = "2025-07-13T20:05:34.266Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, +] + +[[package]] +name = "qh3" +version = "1.5.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/e4/6898c3c3c0d3a5ba62729599edf145acde478cd9d088e5dfd85e3866a610/qh3-1.5.6.tar.gz", hash = "sha256:5c7fb081a07512dcace9a49179a40dc00ad1f77b2779ee4bb7ca176f96552f66", size = 269753, upload-time = "2025-11-09T05:52:49.787Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/7c/11b4240c7e973c2ed2e7d06252faa4f50b346d3a7a83952c5c8a8d53e26c/qh3-1.5.6-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6febfda5cc9decfb6cf0df122b87370b3569b36a9035740756c9d75399f59c9c", size = 4476698, upload-time = "2025-11-09T05:34:38.728Z" }, + { url = "https://files.pythonhosted.org/packages/7f/8d/0ab2d3013cc8c03a68f36282ba1bf31a65cafa952f37bce4b44c2de853a2/qh3-1.5.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57a5c78fce81288e6c28a45db4e8320db2329e728ebdde9cd1787bbd57cec55f", size = 2174544, upload-time = "2025-11-09T05:34:41.592Z" }, + { url = "https://files.pythonhosted.org/packages/6a/8c/70776a12d56cb4275132e707a3ad4e8712f8044f72a948a848eecf29b9ca/qh3-1.5.6-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ec1d69a3671066a4c06f05d00ed966540f4c7a73b062da15d19123a6aa723c3f", size = 1897113, upload-time = "2025-11-09T05:34:43.46Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fd/5d7333743de27ac7cae46c3afa5da75f3dc3892e9041170d25d636b8132c/qh3-1.5.6-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e770b0ed58659a8aec1fe2a323eda188297b941387ef8a308805149ff48700ea", size = 2042349, upload-time = "2025-11-09T05:34:45.354Z" }, + { url = "https://files.pythonhosted.org/packages/89/32/026cb88cb36cda17a8ba8570f4a8eb3fdfed49ffdb28f3d44699f6ebb4a5/qh3-1.5.6-cp313-cp313t-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2ac1dddbcd11d1afc785002a2d0f906bd24ff0b9a18d9f544327bd07a9da877d", size = 2025049, upload-time = "2025-11-09T05:34:47.319Z" }, + { url = "https://files.pythonhosted.org/packages/58/ed/f92681010217ba6712c9b8aeeff0a40a8955a70e11d5ae76fe2daf7075ba/qh3-1.5.6-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ca0751772272e9d65201ca7f84fcf82a00d8599e2adfe3c62aa0249d3bb5602", size = 2068510, upload-time = "2025-11-09T05:34:49.343Z" }, + { url = "https://files.pythonhosted.org/packages/11/cc/6412c82f37da6bd6fb1218aba2e86d0638a7a2573c057bf24137d64b9857/qh3-1.5.6-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08b87bd76d06d225dca95882cac916faf2b178faca3c2d9d1da552174c19be4f", size = 2091524, upload-time = "2025-11-09T05:34:51.203Z" }, + { url = "https://files.pythonhosted.org/packages/17/b3/0f4af1a7e1bed99dedcd24203d504ee356671c056cecf6fd8f7989bf28cf/qh3-1.5.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f631036c4b8e30e033009afababdd04591b25da51a0308d8341b4c27d0f06", size = 2372423, upload-time = "2025-11-09T05:34:53.136Z" }, + { url = "https://files.pythonhosted.org/packages/2a/59/8b3825a34510f8a8e2bd501ffa73ddd5434d092f4f2d8ec9b4834e6c7f1a/qh3-1.5.6-cp313-cp313t-manylinux_2_39_riscv64.whl", hash = "sha256:e40abdfbaf5a8d02b638c3d3d818f6380f3ba5c75b071493ca402c63d361cf55", size = 2033771, upload-time = "2025-11-09T05:34:55.056Z" }, + { url = "https://files.pythonhosted.org/packages/de/af/4a0d3026b3f48ca6cf60b63741e6b62e1435dc489aa068bd26116da44f74/qh3-1.5.6-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:03e8fe16f62a252f05a51f6bfe3dc8e6563cd18d6328fc194da1647632f89f8d", size = 2369697, upload-time = "2025-11-09T05:34:56.956Z" }, + { url = "https://files.pythonhosted.org/packages/6c/db/a18b99c01b4d4ef7d4508d034b702a9cc6788e9099f231090722bb252344/qh3-1.5.6-cp313-cp313t-musllinux_1_1_armv7l.whl", hash = "sha256:6b0994e89783246cf448550817c86380cbde1f65fc8835a489c0361f5ee68da7", size = 2135581, upload-time = "2025-11-09T05:34:58.938Z" }, + { url = "https://files.pythonhosted.org/packages/8b/da/7fe9372887a07381f203236aa1e38dbb58bbed29f463f7e2206958d1c98e/qh3-1.5.6-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:f5bae59549f11e6404451274ae7ca4a80558a01175596d032fd88066f89d103b", size = 2164165, upload-time = "2025-11-09T05:35:00.931Z" }, + { url = "https://files.pythonhosted.org/packages/00/b9/eeca4cb0194f78b2fab49ae40bac881767ab283115fe10579a42d2292904/qh3-1.5.6-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:6e4060949f4b3b4bb3d3aedf0a274d6c40c35f3d856c0345b1ce4cb49847ca4b", size = 2544894, upload-time = "2025-11-09T05:35:02.476Z" }, + { url = "https://files.pythonhosted.org/packages/92/27/5d3409a55b9428c599b9068b2ec8ad2999c338d4c8662db18427934f01c3/qh3-1.5.6-cp313-cp313t-win32.whl", hash = "sha256:91ac8000102b88636854e9b096b5684e06b9c231707e4c9e9440fbe2a493042e", size = 1735030, upload-time = "2025-11-09T05:35:04.424Z" }, + { url = "https://files.pythonhosted.org/packages/00/2d/af22246a43087c0f654f48b3fb648dcfc53eb5eb74242bb1047598be344b/qh3-1.5.6-cp313-cp313t-win_amd64.whl", hash = "sha256:e9dcc8c2ca5b308c42d0e24bd9972e6394d782bac2939901552494e16ac39245", size = 1986491, upload-time = "2025-11-09T05:35:06.863Z" }, + { url = "https://files.pythonhosted.org/packages/9b/06/bab6ea59c2f5c1c8c061f1c24840043585f92c31e6811c3a7005a3598df5/qh3-1.5.6-cp313-cp313t-win_arm64.whl", hash = "sha256:2e66257ee6b1acd449ed9e0290fa500800a25720a3bd12d5d37bd6e815d05ee1", size = 1816042, upload-time = "2025-11-09T05:50:13.263Z" }, + { url = "https://files.pythonhosted.org/packages/4c/5c/6c49f8d12da29eedd048039c1b3c33ffd4db8c2ed4c82afe91d31f00afc4/qh3-1.5.6-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:28b03fe0c7d8989c429426e0744d4eea1ffd976a8fe4e63a0164c2b56e8d4976", size = 4491221, upload-time = "2025-11-09T05:50:40.821Z" }, + { url = "https://files.pythonhosted.org/packages/7a/bc/5942a9189f1452744eeacff89ade2d58a312f11c5a1dd57c183bbd86c9c7/qh3-1.5.6-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1842aa5440b8c94a392202aa19e3593a597fe1e808950de00602bf7d46f6f8a3", size = 2177685, upload-time = "2025-11-09T05:50:42.182Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ab/1c7715bd18db347963bcda00768f387a3935c88d92ccd3292cbcd46edb26/qh3-1.5.6-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9804cf7329364c94075232ff0edaad86bc696c18a4ee6b46b4320b8716737b1a", size = 1898292, upload-time = "2025-11-09T05:50:44.223Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/1f8976a62f280fcd8520bfd627235a6241b30d380084ffa74bfd89530260/qh3-1.5.6-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b64fd616d20028ed06450cf0a6743b739bc46500990003f9dfac7080b83466b", size = 2043209, upload-time = "2025-11-09T05:50:45.742Z" }, + { url = "https://files.pythonhosted.org/packages/00/70/f350c4a61bbe1c3cfb719efef90ee1c609a8986637c1623abbdac00f837c/qh3-1.5.6-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:690bbf3075aa51999f61932da4ccee4f70645059a700da7025709867a39a0868", size = 2027699, upload-time = "2025-11-09T05:50:47.097Z" }, + { url = "https://files.pythonhosted.org/packages/73/27/cea3edc242d65768dbccae3859a260b187e23f98dddf75cad5875cff9beb/qh3-1.5.6-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6987bedcdd8d5d156e21723c4d21575da4cdae31f8eb6b04b64796b68a43ad41", size = 2075827, upload-time = "2025-11-09T05:50:48.684Z" }, + { url = "https://files.pythonhosted.org/packages/8a/3e/8a90dd20618f408983aaff08e0ca9b343cc2b1f29d696827493be14f5c2e/qh3-1.5.6-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11bcca3ffd03e6914f626bbe0f4392b89190ff4fd33a5bdc26b5b1fddae9ab9e", size = 2098224, upload-time = "2025-11-09T05:50:50.159Z" }, + { url = "https://files.pythonhosted.org/packages/01/b8/41e849d7164b6ba1a61f66c6687008d750ee8b605a194a444197a7151d85/qh3-1.5.6-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:692722cd545bcc6c8d6de3ac58ea875f7f43e2cb014be64e267511e8d16bafcd", size = 2375936, upload-time = "2025-11-09T05:50:52.485Z" }, + { url = "https://files.pythonhosted.org/packages/1a/ab/5a9a63901b3bb8a622db523ca785ac14b0e703d55f7796db860dfd671d0c/qh3-1.5.6-cp37-abi3-manylinux_2_39_riscv64.whl", hash = "sha256:91b523f9a7c4d083a831d89663d8aaf45128ad325f3049de4f48678d5e45b211", size = 2039073, upload-time = "2025-11-09T05:50:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d7/be9a2ef6da5da7e6be98a855cc133559bc88da7b5bb21d0c4dde5d71a0c6/qh3-1.5.6-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2f6dd167e6458566825b371a27731092b15a0a527b32e831d21cd4ecb190566a", size = 2370983, upload-time = "2025-11-09T05:50:55.652Z" }, + { url = "https://files.pythonhosted.org/packages/af/e3/ca1eccf6744b77aa744012c4c15350ee7f4e39818786c81ad4ee4a9f7564/qh3-1.5.6-cp37-abi3-musllinux_1_1_armv7l.whl", hash = "sha256:414ad77504a78c521d71ddb8a6d0a1230528ab64184a098424d2ec45c1b570ec", size = 2136965, upload-time = "2025-11-09T05:50:57.181Z" }, + { url = "https://files.pythonhosted.org/packages/08/67/4caf81f598ce0a4a5dc029492ea9cf2c48c1c98921be8c42d8005768b6e2/qh3-1.5.6-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:ef9bfaab22114f8fd36094246f774d8fc5bbc74421aebb742f392feaab04ecb3", size = 2166958, upload-time = "2025-11-09T05:50:58.633Z" }, + { url = "https://files.pythonhosted.org/packages/22/51/196722ef0b0016968e2439720f4dce63ba7f641663cb61ad67bf089c6096/qh3-1.5.6-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:20686c57eb45087e644cd749cdd372e082af4845249eb946ffab9c4c3fb5b364", size = 2546184, upload-time = "2025-11-09T05:51:00.005Z" }, + { url = "https://files.pythonhosted.org/packages/74/e2/20c8c3e21b5465ed9373255216ad4657c58119eff45b99a5e4138c9caf68/qh3-1.5.6-cp37-abi3-win32.whl", hash = "sha256:deefa7d329df97fe4df7b5f2ce806378bb72c1b7b0329439dd8052e916679428", size = 1738876, upload-time = "2025-11-09T05:51:01.701Z" }, + { url = "https://files.pythonhosted.org/packages/31/b4/b67841c3442929caad6c65e937eefe5df7828427fad249e290d13b2df01a/qh3-1.5.6-cp37-abi3-win_amd64.whl", hash = "sha256:84992d0810cc53b33f122cd411be87d36c942e104aa6252d10ee03e1a6d6fb4d", size = 1991436, upload-time = "2025-11-09T05:51:03.438Z" }, +] + +[[package]] +name = "recurring-ical-events" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "icalendar" }, + { name = "python-dateutil" }, + { name = "tzdata" }, + { name = "x-wr-timezone" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/83/90/05dfcc02ecf58bd170305c88db9e3e3933aa73a1f8abac2b326c7fdc1a98/recurring_ical_events-3.8.0.tar.gz", hash = "sha256:3e8c7c35d9bd8956a7ab91afad51477c60d972e1236d3fd1b55087a66bce7d04", size = 602665, upload-time = "2025-06-10T13:23:50.662Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/25/88a4218cccae06ce6b15e41d2f263dd4a73e8e8cbe41537cd7784a17479b/recurring_ical_events-3.8.0-py3-none-any.whl", hash = "sha256:cf958eb17c92d4dca5c621e44c2b3fffd4ba700dca0db66287c5dc11438f63ba", size = 238228, upload-time = "2025-06-10T13:23:49.048Z" }, +] + +[[package]] +name = "redis" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyjwt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/cf/128b1b6d7086200c9f387bd4be9b2572a30b90745ef078bd8b235042dc9f/redis-5.3.1.tar.gz", hash = "sha256:ca49577a531ea64039b5a36db3d6cd1a0c7a60c34124d46924a45b956e8cf14c", size = 4626200, upload-time = "2025-07-25T08:06:27.778Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/26/5c5fa0e83c3621db835cfc1f1d789b37e7fa99ed54423b5f519beb931aa7/redis-5.3.1-py3-none-any.whl", hash = "sha256:dc1909bd24669cc31b5f67a039700b16ec30571096c5f1f0d9d2324bff31af97", size = 272833, upload-time = "2025-07-25T08:06:26.317Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "requests-toolbelt" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, +] + +[[package]] +name = "responses" +version = "0.25.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/95/89c054ad70bfef6da605338b009b2e283485835351a9935c7bfbfaca7ffc/responses-0.25.8.tar.gz", hash = "sha256:9374d047a575c8f781b94454db5cab590b6029505f488d12899ddb10a4af1cf4", size = 79320, upload-time = "2025-08-08T19:01:46.709Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/4c/cc276ce57e572c102d9542d383b2cfd551276581dc60004cb94fe8774c11/responses-0.25.8-py3-none-any.whl", hash = "sha256:0c710af92def29c8352ceadff0c3fe340ace27cf5af1bbe46fb71275bcd2831c", size = 34769, upload-time = "2025-08-08T19:01:45.018Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, +] + +[[package]] +name = "ruff" +version = "0.14.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/5b/dd7406afa6c95e3d8fa9d652b6d6dd17dd4a6bf63cb477014e8ccd3dcd46/ruff-0.14.7.tar.gz", hash = "sha256:3417deb75d23bd14a722b57b0a1435561db65f0ad97435b4cf9f85ffcef34ae5", size = 5727324, upload-time = "2025-11-28T20:55:10.525Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/b1/7ea5647aaf90106f6d102230e5df874613da43d1089864da1553b899ba5e/ruff-0.14.7-py3-none-linux_armv6l.whl", hash = "sha256:b9d5cb5a176c7236892ad7224bc1e63902e4842c460a0b5210701b13e3de4fca", size = 13414475, upload-time = "2025-11-28T20:54:54.569Z" }, + { url = "https://files.pythonhosted.org/packages/af/19/fddb4cd532299db9cdaf0efdc20f5c573ce9952a11cb532d3b859d6d9871/ruff-0.14.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3f64fe375aefaf36ca7d7250292141e39b4cea8250427482ae779a2aa5d90015", size = 13634613, upload-time = "2025-11-28T20:55:17.54Z" }, + { url = "https://files.pythonhosted.org/packages/40/2b/469a66e821d4f3de0440676ed3e04b8e2a1dc7575cf6fa3ba6d55e3c8557/ruff-0.14.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93e83bd3a9e1a3bda64cb771c0d47cda0e0d148165013ae2d3554d718632d554", size = 12765458, upload-time = "2025-11-28T20:55:26.128Z" }, + { url = "https://files.pythonhosted.org/packages/f1/05/0b001f734fe550bcfde4ce845948ac620ff908ab7241a39a1b39bb3c5f49/ruff-0.14.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3838948e3facc59a6070795de2ae16e5786861850f78d5914a03f12659e88f94", size = 13236412, upload-time = "2025-11-28T20:55:28.602Z" }, + { url = "https://files.pythonhosted.org/packages/11/36/8ed15d243f011b4e5da75cd56d6131c6766f55334d14ba31cce5461f28aa/ruff-0.14.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24c8487194d38b6d71cd0fd17a5b6715cda29f59baca1defe1e3a03240f851d1", size = 13182949, upload-time = "2025-11-28T20:55:33.265Z" }, + { url = "https://files.pythonhosted.org/packages/3b/cf/fcb0b5a195455729834f2a6eadfe2e4519d8ca08c74f6d2b564a4f18f553/ruff-0.14.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79c73db6833f058a4be8ffe4a0913b6d4ad41f6324745179bd2aa09275b01d0b", size = 13816470, upload-time = "2025-11-28T20:55:08.203Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5d/34a4748577ff7a5ed2f2471456740f02e86d1568a18c9faccfc73bd9ca3f/ruff-0.14.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:12eb7014fccff10fc62d15c79d8a6be4d0c2d60fe3f8e4d169a0d2def75f5dad", size = 15289621, upload-time = "2025-11-28T20:55:30.837Z" }, + { url = "https://files.pythonhosted.org/packages/53/53/0a9385f047a858ba133d96f3f8e3c9c66a31cc7c4b445368ef88ebeac209/ruff-0.14.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c623bbdc902de7ff715a93fa3bb377a4e42dd696937bf95669118773dbf0c50", size = 14975817, upload-time = "2025-11-28T20:55:24.107Z" }, + { url = "https://files.pythonhosted.org/packages/a8/d7/2f1c32af54c3b46e7fadbf8006d8b9bcfbea535c316b0bd8813d6fb25e5d/ruff-0.14.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f53accc02ed2d200fa621593cdb3c1ae06aa9b2c3cae70bc96f72f0000ae97a9", size = 14284549, upload-time = "2025-11-28T20:55:06.08Z" }, + { url = "https://files.pythonhosted.org/packages/92/05/434ddd86becd64629c25fb6b4ce7637dd52a45cc4a4415a3008fe61c27b9/ruff-0.14.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:281f0e61a23fcdcffca210591f0f53aafaa15f9025b5b3f9706879aaa8683bc4", size = 14071389, upload-time = "2025-11-28T20:55:35.617Z" }, + { url = "https://files.pythonhosted.org/packages/ff/50/fdf89d4d80f7f9d4f420d26089a79b3bb1538fe44586b148451bc2ba8d9c/ruff-0.14.7-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:dbbaa5e14148965b91cb090236931182ee522a5fac9bc5575bafc5c07b9f9682", size = 14202679, upload-time = "2025-11-28T20:55:01.472Z" }, + { url = "https://files.pythonhosted.org/packages/77/54/87b34988984555425ce967f08a36df0ebd339bb5d9d0e92a47e41151eafc/ruff-0.14.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1464b6e54880c0fe2f2d6eaefb6db15373331414eddf89d6b903767ae2458143", size = 13147677, upload-time = "2025-11-28T20:55:19.933Z" }, + { url = "https://files.pythonhosted.org/packages/67/29/f55e4d44edfe053918a16a3299e758e1c18eef216b7a7092550d7a9ec51c/ruff-0.14.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f217ed871e4621ea6128460df57b19ce0580606c23aeab50f5de425d05226784", size = 13151392, upload-time = "2025-11-28T20:55:21.967Z" }, + { url = "https://files.pythonhosted.org/packages/36/69/47aae6dbd4f1d9b4f7085f4d9dcc84e04561ee7ad067bf52e0f9b02e3209/ruff-0.14.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6be02e849440ed3602d2eb478ff7ff07d53e3758f7948a2a598829660988619e", size = 13412230, upload-time = "2025-11-28T20:55:12.749Z" }, + { url = "https://files.pythonhosted.org/packages/b7/4b/6e96cb6ba297f2ba502a231cd732ed7c3de98b1a896671b932a5eefa3804/ruff-0.14.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19a0f116ee5e2b468dfe80c41c84e2bbd6b74f7b719bee86c2ecde0a34563bcc", size = 14195397, upload-time = "2025-11-28T20:54:56.896Z" }, + { url = "https://files.pythonhosted.org/packages/69/82/251d5f1aa4dcad30aed491b4657cecd9fb4274214da6960ffec144c260f7/ruff-0.14.7-py3-none-win32.whl", hash = "sha256:e33052c9199b347c8937937163b9b149ef6ab2e4bb37b042e593da2e6f6cccfa", size = 13126751, upload-time = "2025-11-28T20:55:03.47Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b5/d0b7d145963136b564806f6584647af45ab98946660d399ec4da79cae036/ruff-0.14.7-py3-none-win_amd64.whl", hash = "sha256:e17a20ad0d3fad47a326d773a042b924d3ac31c6ca6deb6c72e9e6b5f661a7c6", size = 14531726, upload-time = "2025-11-28T20:54:59.121Z" }, + { url = "https://files.pythonhosted.org/packages/1d/d2/1637f4360ada6a368d3265bf39f2cf737a0aaab15ab520fc005903e883f8/ruff-0.14.7-py3-none-win_arm64.whl", hash = "sha256:be4d653d3bea1b19742fcc6502354e32f65cd61ff2fbdb365803ef2c2aec6228", size = 13609215, upload-time = "2025-11-28T20:55:15.375Z" }, +] + +[[package]] +name = "sentry-sdk" +version = "2.46.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/d7/c140a5837649e2bf2ec758494fde1d9a016c76777eab64e75ef38d685bbb/sentry_sdk-2.46.0.tar.gz", hash = "sha256:91821a23460725734b7741523021601593f35731808afc0bb2ba46c27b8acd91", size = 374761, upload-time = "2025-11-24T09:34:13.932Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/b6/ce7c502a366f4835b1f9c057753f6989a92d3c70cbadb168193f5fb7499b/sentry_sdk-2.46.0-py2.py3-none-any.whl", hash = "sha256:4eeeb60198074dff8d066ea153fa6f241fef1668c10900ea53a4200abc8da9b1", size = 406266, upload-time = "2025-11-24T09:34:12.114Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sqlparse" +version = "0.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/76/437d71068094df0726366574cf3432a4ed754217b436eb7429415cf2d480/sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e", size = 120815, upload-time = "2025-12-19T07:17:45.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/4b/359f28a903c13438ef59ebeee215fb25da53066db67b305c125f1c6d2a25/sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba", size = 46138, upload-time = "2025-12-19T07:17:46.573Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + +[[package]] +name = "types-requests" +version = "2.32.4.20250913" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/27/489922f4505975b11de2b5ad07b4fe1dca0bca9be81a703f26c5f3acfce5/types_requests-2.32.4.20250913.tar.gz", hash = "sha256:abd6d4f9ce3a9383f269775a9835a4c24e5cd6b9f647d64f88aa4613c33def5d", size = 23113, upload-time = "2025-09-13T02:40:02.309Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/20/9a227ea57c1285986c4cf78400d0a91615d25b24e257fd9e2969606bdfae/types_requests-2.32.4.20250913-py3-none-any.whl", hash = "sha256:78c9c1fffebbe0fa487a418e0fa5252017e9c60d1a2da394077f1780f655d7e1", size = 20658, upload-time = "2025-09-13T02:40:01.115Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +] + +[[package]] +name = "tzlocal" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" }, +] + +[[package]] +name = "uritemplate" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/60/f174043244c5306c9988380d2cb10009f91563fc4b31293d27e17201af56/uritemplate-4.2.0.tar.gz", hash = "sha256:480c2ed180878955863323eea31b0ede668795de182617fef9c6ca09e6ec9d0e", size = 33267, upload-time = "2025-06-02T15:12:06.318Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/99/3ae339466c9183ea5b8ae87b34c0b897eda475d2aec2307cae60e5cd4f29/uritemplate-4.2.0-py3-none-any.whl", hash = "sha256:962201ba1c4edcab02e60f9a0d3821e82dfc5d2d6662a21abd533879bdb8a686", size = 11488, upload-time = "2025-06-02T15:12:03.405Z" }, +] + +[[package]] +name = "url-normalize" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/31/febb777441e5fcdaacb4522316bf2a527c44551430a4873b052d545e3279/url_normalize-2.2.1.tar.gz", hash = "sha256:74a540a3b6eba1d95bdc610c24f2c0141639f3ba903501e61a52a8730247ff37", size = 18846, upload-time = "2025-04-26T20:37:58.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/d9/5ec15501b675f7bc07c5d16aa70d8d778b12375686b6efd47656efdc67cd/url_normalize-2.2.1-py3-none-any.whl", hash = "sha256:3deb687587dc91f7b25c9ae5162ffc0f057ae85d22b1e15cf5698311247f567b", size = 14728, upload-time = "2025-04-26T20:37:57.217Z" }, +] + +[[package]] +name = "urllib3" +version = "2.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, +] + +[[package]] +name = "urllib3-future" +version = "2.15.901" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, + { name = "jh2" }, + { name = "qh3", marker = "(platform_machine == 'AMD64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'ARM64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'arm64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'armv7l' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'i686' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'ppc64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'ppc64le' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'riscv64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'riscv64gc' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 's390x' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'x86' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'x86_64' and platform_python_implementation == 'CPython' and sys_platform == 'darwin') or (platform_machine == 'AMD64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'ARM64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'arm64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'armv7l' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'i686' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'ppc64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'ppc64le' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'riscv64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'riscv64gc' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 's390x' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'x86' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'x86_64' and platform_python_implementation == 'CPython' and sys_platform == 'linux') or (platform_machine == 'AMD64' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'ARM64' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'arm64' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'armv7l' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'i686' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'ppc64' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'ppc64le' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'riscv64' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'riscv64gc' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 's390x' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'x86' and platform_python_implementation == 'CPython' and sys_platform == 'win32') or (platform_machine == 'x86_64' and platform_python_implementation == 'CPython' and sys_platform == 'win32')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1a/3d/ea375148eb25560c93a9cca9d7e23061150641f6c641c03d4d76bbc9d0a2/urllib3_future-2.15.901.tar.gz", hash = "sha256:a8ca77c6a3c8c1172511f45ba4358d2a682474580f75b2d234b1e427c58c922f", size = 1116237, upload-time = "2025-12-22T07:53:55.453Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/f9/3abec381843b5abbf2ce2cfd14b643c1c7808bdc1389aa13dd4fb378b454/urllib3_future-2.15.901-py3-none-any.whl", hash = "sha256:e88e2a835a4b75fd3dc4e9ccb3ba71e1000a8a98a43e0975e1d5be652beb2507", size = 684722, upload-time = "2025-12-22T07:53:53.694Z" }, +] + +[[package]] +name = "vine" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/e4/d07b5f29d283596b9727dd5275ccbceb63c44a1a82aa9e4bfd20426762ac/vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0", size = 48980, upload-time = "2023-11-05T08:46:53.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/ff/7c0c86c43b3cbb927e0ccc0255cb4057ceba4799cd44ae95174ce8e8b5b2/vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc", size = 9636, upload-time = "2023-11-05T08:46:51.205Z" }, +] + +[[package]] +name = "wassima" +version = "2.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/1a/992d314e789b41513a285d28a4268cd9228a029a7913d976575f174d8c13/wassima-2.0.3.tar.gz", hash = "sha256:f86578e33e46e12352964ced83ec5a739ff77791e96224f980a043fa5ac563e8", size = 149031, upload-time = "2025-12-16T07:27:37.192Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/b1/52cb74011569cbc57dae499ed8d317098976bd22246b0e464282d3c1651f/wassima-2.0.3-py3-none-any.whl", hash = "sha256:019e0810ca643c5a63fe6f0a46c9a660200abd9588c07ba1fdff2545ade2aa1c", size = 144270, upload-time = "2025-12-16T07:27:35.735Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, +] + +[[package]] +name = "whitenoise" +version = "6.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/95/8c81ec6b6ebcbf8aca2de7603070ccf37dbb873b03f20708e0f7c1664bc6/whitenoise-6.11.0.tar.gz", hash = "sha256:0f5bfce6061ae6611cd9396a8231e088722e4fc67bc13a111be74c738d99375f", size = 26432, upload-time = "2025-09-18T09:16:10.995Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/e9/4366332f9295fe0647d7d3251ce18f5615fbcb12d02c79a26f8dba9221b3/whitenoise-6.11.0-py3-none-any.whl", hash = "sha256:b2aeb45950597236f53b5342b3121c5de69c8da0109362aee506ce88e022d258", size = 20197, upload-time = "2025-09-18T09:16:09.754Z" }, +] + +[[package]] +name = "x-wr-timezone" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "icalendar" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/2b/8ae5f59ab852c8fe32dd37c1aa058eb98aca118fec2d3af5c3cd56fffb7b/x_wr_timezone-2.0.1.tar.gz", hash = "sha256:9166c40e6ffd4c0edebabc354e1a1e2cffc1bb473f88007694793757685cc8c3", size = 18212, upload-time = "2025-02-06T17:10:40.913Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/b7/4bac35b4079b76c07d8faddf89467e9891b1610cfe8d03b0ebb5610e4423/x_wr_timezone-2.0.1-py3-none-any.whl", hash = "sha256:e74a53b9f4f7def8138455c240e65e47c224778bce3c024fcd6da2cbe91ca038", size = 11102, upload-time = "2025-02-06T17:10:39.192Z" }, +] diff --git a/src/frontend/.dockerignore b/src/frontend/.dockerignore new file mode 100644 index 0000000..ec39f24 --- /dev/null +++ b/src/frontend/.dockerignore @@ -0,0 +1,29 @@ + +# System-specific files +.DS_Store +**/.DS_Store + +# Docker +compose.* +env.d + +# Docs +docs +*.md +*.log + +# Development/test cache & configurations +data +.cache +.circleci +.git +.vscode +.iml +.idea +db.sqlite3 +.mypy_cache +.pylint.d +.pytest_cache + +# Frontend +node_modules diff --git a/src/frontend/Dockerfile b/src/frontend/Dockerfile new file mode 100644 index 0000000..19d9d59 --- /dev/null +++ b/src/frontend/Dockerfile @@ -0,0 +1,72 @@ +FROM node:22-alpine AS frontend-deps + +WORKDIR /home/frontend/ + +COPY ./package.json ./package.json +COPY ./yarn.lock ./yarn.lock +COPY ./apps/calendars/package.json ./apps/calendars/package.json +COPY ./packages/open-calendar/package.json ./packages/open-calendar/package.json + +RUN yarn install --frozen-lockfile + +COPY .dockerignore ./.dockerignore +# COPY ./.prettierrc.js ./.prettierrc.js +#COPY ./packages/eslint-config-calendars ./packages/eslint-config-calendars +COPY ./packages/open-calendar ./packages/open-calendar +COPY ./apps/calendars ./apps/calendars + +# Build open-calendar package +WORKDIR /home/frontend/packages/open-calendar +RUN yarn build +WORKDIR /home/frontend + +### ---- Front-end builder image ---- +FROM frontend-deps AS calendars + +WORKDIR /home/frontend/apps/calendars + +FROM frontend-deps AS calendars-dev + +WORKDIR /home/frontend/apps/calendars + +EXPOSE 3000 + +RUN yarn build-theme + +# Build open-calendar package if dist doesn't exist, then start dev server +CMD ["/bin/sh", "-c", "cd /home/frontend/packages/open-calendar && ([ -d dist ] || yarn build) && cd /home/frontend/apps/calendars && yarn dev"] + +# Tilt will rebuild calendars target so, we dissociate calendars and calendars-builder +# to avoid rebuilding the app at every changes. +FROM calendars AS calendars-builder + +WORKDIR /home/frontend/apps/calendars + +ARG API_ORIGIN +ENV NEXT_PUBLIC_API_ORIGIN=${API_ORIGIN} + +RUN yarn build + +# ---- Front-end image ---- +FROM nginxinc/nginx-unprivileged:alpine3.22 AS frontend-production + +# Upgrade system packages to install security updates +USER root +RUN apk update && \ + apk upgrade && \ + rm -rf /var/cache/apk/* + +# Un-privileged user running the application +ARG DOCKER_USER +USER ${DOCKER_USER} + +COPY --from=calendars-builder \ + /home/frontend/apps/calendars/out \ + /usr/share/nginx/html + +COPY ./apps/calendars/conf/default.conf /etc/nginx/conf.d +COPY ./docker/files/usr/local/bin/entrypoint /usr/local/bin/entrypoint + +ENTRYPOINT [ "/usr/local/bin/entrypoint" ] + +CMD ["nginx", "-g", "daemon off;"] diff --git a/src/frontend/apps/calendars/.env b/src/frontend/apps/calendars/.env new file mode 100644 index 0000000..8f22306 --- /dev/null +++ b/src/frontend/apps/calendars/.env @@ -0,0 +1 @@ +NEXT_PUBLIC_API_ORIGIN= \ No newline at end of file diff --git a/src/frontend/apps/calendars/.env.development b/src/frontend/apps/calendars/.env.development new file mode 100644 index 0000000..73c257c --- /dev/null +++ b/src/frontend/apps/calendars/.env.development @@ -0,0 +1 @@ +NEXT_PUBLIC_API_ORIGIN=http://localhost:8921 diff --git a/src/frontend/apps/calendars/.gitignore b/src/frontend/apps/calendars/.gitignore new file mode 100644 index 0000000..6fc1b4d --- /dev/null +++ b/src/frontend/apps/calendars/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/src/frontend/apps/calendars/README.md b/src/frontend/apps/calendars/README.md new file mode 100644 index 0000000..ef0e47e --- /dev/null +++ b/src/frontend/apps/calendars/README.md @@ -0,0 +1,40 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/pages/api-reference/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) instead of React pages. + +This project uses [`next/font`](https://nextjs.org/docs/pages/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn-pages-router) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/pages/building-your-application/deploying) for more details. diff --git a/src/frontend/apps/calendars/__mocks__/fileMock.js b/src/frontend/apps/calendars/__mocks__/fileMock.js new file mode 100644 index 0000000..57a4949 --- /dev/null +++ b/src/frontend/apps/calendars/__mocks__/fileMock.js @@ -0,0 +1,2 @@ +module.exports = "test-file-stub"; + diff --git a/src/frontend/apps/calendars/conf/default.conf b/src/frontend/apps/calendars/conf/default.conf new file mode 100644 index 0000000..ed0be68 --- /dev/null +++ b/src/frontend/apps/calendars/conf/default.conf @@ -0,0 +1,26 @@ +server { + listen 8080; + listen 3000; + server_name localhost; + + root /usr/share/nginx/html; + + add_header X-Frame-Options DENY always; + + location / { + try_files $uri index.html $uri/ =404; + } + + location ~ "^/401/?$" { + try_files $uri /401.html; + } + + location ~ "^/403/?$" { + try_files $uri /403.html; + } + + error_page 404 /404.html; + location = /404.html { + internal; + } +} diff --git a/src/frontend/apps/calendars/cunningham.ts b/src/frontend/apps/calendars/cunningham.ts new file mode 100644 index 0000000..7e13183 --- /dev/null +++ b/src/frontend/apps/calendars/cunningham.ts @@ -0,0 +1,411 @@ +import { cunninghamConfig } from "@gouvfr-lasuite/ui-kit"; + +// TODO: Temporary solution to override the default button tertiary text color, waiting for the new ui-kit to be released + +/** + * Deep merge function that recursively merges objects + * @param target - The target object to merge into + * @param source - The source object to merge from + * @returns A new object with deeply merged properties + * + * @example + * const obj1 = { a: { x: 1, y: 2 }, b: 3 }; + * const obj2 = { a: { y: 3, z: 4 }, c: 5 }; + * const merged = deepMerge(obj1, obj2); + * // Result: { a: { x: 1, y: 3, z: 4 }, b: 3, c: 5 } + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function deepMerge(target: any, source: any): any { + const result = { ...target }; + + for (const key in source) { + if (source.hasOwnProperty(key)) { + const sourceValue = source[key]; + const targetValue = result[key]; + + if ( + sourceValue && + typeof sourceValue === "object" && + !Array.isArray(sourceValue) && + targetValue && + typeof targetValue === "object" && + !Array.isArray(targetValue) + ) { + // Recursively merge nested objects + result[key] = deepMerge(targetValue, sourceValue); + } else if (sourceValue !== undefined) { + // Override with source value + result[key] = sourceValue; + } + } + } + + return result; +} + +const themesImages = { + anct: { + favicon: "/assets/anct_favicon.png", + logo: "/assets/anct_logo_beta.svg", + "logo-icon": "/assets/anct_logo-icon.svg", + }, + dark: { + favicon: "/assets/favicon.png", + logo: "/assets/logo_beta.svg", + "logo-icon": "/assets/logo-icon_beta.svg", + }, + default: { + favicon: "/assets/favicon.png", + logo: "/assets/logo_beta.svg", + "logo-icon": "/assets/logo-icon_beta.svg", + }, +}; + +const themesGaufre = { + anct: { + widgetPath: "https://static.suite.anct.gouv.fr/widgets/lagaufre.js", + apiUrl: + "https://operateurs.suite.anct.gouv.fr/api/v1.0/lagaufre/services/?operator=9f5624fc-ef99-4d10-ae3f-403a81eb16ef&siret=21870030000013", + }, + dark: { + widgetPath: "https://static.suite.anct.gouv.fr/widgets/lagaufre.js", + apiUrl: "https://lasuite.numerique.gouv.fr/api/services", + }, + default: { + widgetPath: "https://static.suite.anct.gouv.fr/widgets/lagaufre.js", + apiUrl: "https://lasuite.numerique.gouv.fr/api/services", + }, +}; + +const getComponents = (theme: keyof typeof themesImages) => { + return { + datagrid: { + "body--background-color-hover": + "ref(contextuals.background.semantic.contextual.primary)", + }, + gaufre: { + widgetPath: `'${themesGaufre[theme].widgetPath}'`, + apiUrl: `'${themesGaufre[theme].apiUrl}'`, + }, + favicon: { + src: `'${themesImages[theme].favicon}'`, + }, + logo: { + src: `url('${themesImages[theme].logo}')`, + }, + "logo-icon": { + src: `url('${themesImages[theme]["logo-icon"]}')`, + }, + }; +}; + +const defaultConfig = deepMerge(cunninghamConfig, { + themes: { + anct: { + globals: { + colors: { + "brand-050": "#EEF0F9", + "brand-100": "#DDE2F5", + "brand-150": "#CBD4F1", + "brand-200": "#B8C6F0", + "brand-250": "#A5B7F2", + "brand-300": "#91A8F7", + "brand-350": "#7C98FE", + "brand-400": "#6A89FF", + "brand-450": "#5A7AFB", + "brand-500": "#4B6BF0", + "brand-550": "#3E5CE7", + "brand-600": "#3352D5", + "brand-650": "#2A47C0", + "brand-700": "#2340A3", + "brand-750": "#223A7F", + "brand-800": "#1F325F", + "brand-850": "#1B2845", + "brand-900": "#151E30", + "brand-950": "#0D121D", + "gray-000": "#FFFFFF", + "gray-025": "#F6F8FA", + "gray-050": "#ECF1F7", + "gray-100": "#DDE3F3", + "gray-150": "#CCD4EA", + "gray-200": "#BCC7E0", + "gray-250": "#AEB9D2", + "gray-300": "#A1ABC4", + "gray-350": "#949EB6", + "gray-400": "#8791A9", + "gray-450": "#7A849B", + "gray-500": "#6D778E", + "gray-550": "#616A81", + "gray-600": "#555E75", + "gray-650": "#495268", + "gray-700": "#3E475C", + "gray-750": "#333B50", + "gray-800": "#283044", + "gray-850": "#1E2539", + "gray-900": "#171B28", + "gray-950": "#0F1118", + "gray-1000": "#000000", + "info-050": "#E9F2F8", + "info-100": "#D2E5F1", + "info-150": "#C0D7F0", + "info-200": "#AEC8F0", + "info-250": "#9EB9F2", + "info-300": "#8DABEE", + "info-350": "#7B9DE9", + "info-400": "#6E8FDB", + "info-450": "#6282CD", + "info-500": "#5575BF", + "info-550": "#4968B1", + "info-600": "#3E5CA3", + "info-650": "#344F97", + "info-700": "#294389", + "info-750": "#243972", + "info-800": "#1D2F5B", + "info-850": "#1A2744", + "info-900": "#151D2F", + "info-950": "#0E131F", + "success-050": "#E7F1E9", + "success-100": "#CFE3D3", + "success-150": "#B9D8C0", + "success-200": "#A1CEAC", + "success-250": "#85C496", + "success-300": "#63BC7F", + "success-350": "#45B16B", + "success-400": "#1CA659", + "success-450": "#00984C", + "success-500": "#008A3F", + "success-550": "#007C32", + "success-600": "#006E24", + "success-650": "#016016", + "success-700": "#005305", + "success-750": "#0D450A", + "success-800": "#11380E", + "success-850": "#132A11", + "success-900": "#101E0F", + "success-950": "#091209", + "warning-050": "#F6F0E8", + "warning-100": "#EDE2D1", + "warning-150": "#E6D3B8", + "warning-200": "#E3C39F", + "warning-250": "#E3B082", + "warning-300": "#E19E5C", + "warning-350": "#D98E3F", + "warning-400": "#CF7D19", + "warning-450": "#C17000", + "warning-500": "#B36300", + "warning-550": "#A45600", + "warning-600": "#964900", + "warning-650": "#893C00", + "warning-700": "#7B2F00", + "warning-750": "#68270D", + "warning-800": "#562013", + "warning-850": "#411D18", + "warning-900": "#2E1714", + "warning-950": "#1D0F0D", + "error-050": "#F9EFEC", + "error-100": "#F4DFD9", + "error-150": "#F0CEC6", + "error-200": "#EEBCB2", + "error-250": "#EEA99D", + "error-300": "#EF9487", + "error-350": "#F37C6E", + "error-400": "#F65F53", + "error-450": "#EF443C", + "error-500": "#E0342E", + "error-550": "#D0201F", + "error-600": "#C0000C", + "error-650": "#AA0000", + "error-700": "#910C06", + "error-750": "#731E16", + "error-800": "#58201A", + "error-850": "#411D18", + "error-900": "#2E1714", + "error-950": "#1D0F0D", + "red-050": "#F9EFEC", + "red-100": "#F4DEDA", + "red-150": "#F0CDC9", + "red-200": "#EEBBB6", + "red-250": "#EEA8A2", + "red-300": "#F0938D", + "red-350": "#EC7E78", + "red-400": "#E46D67", + "red-450": "#D95B58", + "red-500": "#CA4E4B", + "red-550": "#BB403F", + "red-600": "#AC3233", + "red-650": "#9D2227", + "red-700": "#882023", + "red-750": "#721D1B", + "red-800": "#58201A", + "red-850": "#401D18", + "red-900": "#2E1714", + "red-950": "#1D0F0D", + "orange-050": "#F8F0E9", + "orange-100": "#F1E0D3", + "orange-150": "#ECD0BD", + "orange-200": "#E9C0A5", + "orange-250": "#E8AE8A", + "orange-300": "#EB9870", + "orange-350": "#EB845A", + "orange-400": "#E66E37", + "orange-450": "#DD5B16", + "orange-500": "#CE4D00", + "orange-550": "#BF3E00", + "orange-600": "#B02F00", + "orange-650": "#A11E00", + "orange-700": "#8A1E14", + "orange-750": "#731E16", + "orange-800": "#58201A", + "orange-850": "#401D18", + "orange-900": "#2E1714", + "orange-950": "#1D0F0D", + "brown-050": "#F5F0E8", + "brown-100": "#ECE2D1", + "brown-150": "#E9D1B9", + "brown-200": "#E3C19D", + "brown-250": "#DCB187", + "brown-300": "#D2A26F", + "brown-350": "#C49562", + "brown-400": "#B68855", + "brown-450": "#A97B48", + "brown-500": "#9B6E3B", + "brown-550": "#8E612F", + "brown-600": "#815521", + "brown-650": "#744913", + "brown-700": "#673D00", + "brown-750": "#5A3100", + "brown-800": "#4E2600", + "brown-850": "#3D1F0B", + "brown-900": "#2C170F", + "brown-950": "#1C0F0B", + "yellow-050": "#F3F0E7", + "yellow-100": "#E9E2CF", + "yellow-150": "#E0D4B7", + "yellow-200": "#DAC59A", + "yellow-250": "#D5B67A", + "yellow-300": "#D0A559", + "yellow-350": "#CC9331", + "yellow-400": "#C48400", + "yellow-450": "#B77600", + "yellow-500": "#AA6800", + "yellow-550": "#9D5A00", + "yellow-600": "#914D00", + "yellow-650": "#843F00", + "yellow-700": "#773200", + "yellow-750": "#6A2601", + "yellow-800": "#56210F", + "yellow-850": "#401D16", + "yellow-900": "#2E1714", + "yellow-950": "#1D0F0D", + "green-050": "#E3F1EF", + "green-100": "#CAE5E1", + "green-150": "#B0DBD4", + "green-200": "#91D1C7", + "green-250": "#6AC8BC", + "green-300": "#4DBCAF", + "green-350": "#3CAFA2", + "green-400": "#2AA194", + "green-450": "#109487", + "green-500": "#00867A", + "green-550": "#00786D", + "green-600": "#016A60", + "green-650": "#015D53", + "green-700": "#005047", + "green-750": "#00443B", + "green-800": "#00382F", + "green-850": "#002C25", + "green-900": "#041F1A", + "green-950": "#041310", + "blue1-050": "#EAF2F9", + "blue1-100": "#D4E4F3", + "blue1-150": "#BFD7F0", + "blue1-200": "#AAC9EF", + "blue1-250": "#96BBF1", + "blue1-300": "#82ACF6", + "blue1-350": "#709BFE", + "blue1-400": "#608BFF", + "blue1-450": "#537BFB", + "blue1-500": "#476DEC", + "blue1-550": "#3C60DD", + "blue1-600": "#3252CF", + "blue1-650": "#2B48B9", + "blue1-700": "#28409B", + "blue1-750": "#24397E", + "blue1-800": "#223260", + "blue1-850": "#1F2A48", + "blue1-900": "#191F32", + "blue1-950": "#111320", + "blue2-050": "#E5F2F3", + "blue2-100": "#CDE6EC", + "blue2-150": "#B7D9EA", + "blue2-200": "#9BCDE7", + "blue2-250": "#84C1E0", + "blue2-300": "#6BB4D8", + "blue2-350": "#5CA6CB", + "blue2-400": "#4D99BC", + "blue2-450": "#3E8CAE", + "blue2-500": "#2F7FA2", + "blue2-550": "#1F7295", + "blue2-600": "#056688", + "blue2-650": "#00597B", + "blue2-700": "#004C6C", + "blue2-750": "#003F5E", + "blue2-800": "#003353", + "blue2-850": "#0C273E", + "blue2-900": "#0E1C2C", + "blue2-950": "#0A121C", + "purple-050": "#EDF1FA", + "purple-100": "#DCE2F5", + "purple-150": "#CCD4F1", + "purple-200": "#BCC4F0", + "purple-250": "#ADB6F2", + "purple-300": "#9EA6F6", + "purple-350": "#8E95FD", + "purple-400": "#8083FF", + "purple-450": "#7173FF", + "purple-500": "#6665F1", + "purple-550": "#5B57E2", + "purple-600": "#5049D4", + "purple-650": "#4641BC", + "purple-700": "#3D39A2", + "purple-750": "#363680", + "purple-800": "#2E3162", + "purple-850": "#242848", + "purple-900": "#1C1E32", + "purple-950": "#121320", + "pink-050": "#F8EFF4", + "pink-100": "#F0DEE9", + "pink-150": "#EBCDDF", + "pink-200": "#E7BDD6", + "pink-250": "#E5A9CC", + "pink-300": "#E695C0", + "pink-350": "#EA7CAE", + "pink-400": "#E4659F", + "pink-450": "#DD4F93", + "pink-500": "#CD4085", + "pink-550": "#BE3279", + "pink-600": "#AE216D", + "pink-650": "#9B195D", + "pink-700": "#86164E", + "pink-750": "#6E1B3D", + "pink-800": "#551E31", + "pink-850": "#3F1C24", + "pink-900": "#2D161A", + "pink-950": "#1C0E10", + }, + }, + components: getComponents("anct"), + }, + dark: { + globals: cunninghamConfig.themes.default.globals, + components: getComponents("dark"), + }, + default: { + components: getComponents("default"), + }, + }, +}); + +const config = defaultConfig; + +export default config; diff --git a/src/frontend/apps/calendars/eslint.config.mjs b/src/frontend/apps/calendars/eslint.config.mjs new file mode 100644 index 0000000..93ffbd0 --- /dev/null +++ b/src/frontend/apps/calendars/eslint.config.mjs @@ -0,0 +1,22 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), + { + rules: { + "react-hooks/exhaustive-deps": "off", + "@next/next/no-img-element": "off", + }, + }, +]; + +export default eslintConfig; diff --git a/src/frontend/apps/calendars/jest.config.ts b/src/frontend/apps/calendars/jest.config.ts new file mode 100644 index 0000000..8f83dcd --- /dev/null +++ b/src/frontend/apps/calendars/jest.config.ts @@ -0,0 +1,39 @@ +import type { Config } from "jest"; +import { pathsToModuleNameMapper } from "ts-jest"; +import tsconfig from "./tsconfig.json"; + +const config: Config = { + preset: "ts-jest", + testEnvironment: "node", + roots: ["/src"], + testMatch: ["**/__tests__/**/*.test.ts", "**/__tests__/**/*.test.tsx"], + moduleNameMapper: { + // Handle static assets FIRST (before path aliases) + "\\.(css|less|scss|sass|svg|png|jpg|jpeg|gif)$": + "/__mocks__/fileMock.js", + // Then handle path aliases + ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths || {}, { + prefix: "/", + }), + }, + transform: { + "^.+\\.(ts|tsx)$": [ + "ts-jest", + { + tsconfig: { + jsx: "react", + moduleResolution: "node", + }, + }, + ], + }, + transformIgnorePatterns: ["node_modules/(?!(.*\\.mjs$))"], + moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "svg"], + collectCoverageFrom: [ + "src/**/*.{ts,tsx}", + "!src/**/*.d.ts", + "!src/**/__tests__/**", + ], +}; + +export default config; diff --git a/src/frontend/apps/calendars/next.config.ts b/src/frontend/apps/calendars/next.config.ts new file mode 100644 index 0000000..3cc9059 --- /dev/null +++ b/src/frontend/apps/calendars/next.config.ts @@ -0,0 +1,21 @@ +import type { NextConfig } from "next"; +import path from "path"; + +const nextConfig: NextConfig = { + output: "export", + debug: process.env.NODE_ENV === "development", + reactStrictMode: false, + webpack: (config, { isServer }) => { + // Resolve workspace packages + config.resolve.alias = { + ...config.resolve.alias, + "open-dav-calendar": path.resolve( + __dirname, + "../../packages/open-calendar/dist/index.js" + ), + }; + return config; + }, +}; + +export default nextConfig; diff --git a/src/frontend/apps/calendars/package.json b/src/frontend/apps/calendars/package.json new file mode 100644 index 0000000..5930bc2 --- /dev/null +++ b/src/frontend/apps/calendars/package.json @@ -0,0 +1,54 @@ +{ + "name": "calendars", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build --no-lint", + "start": "next start", + "lint": "next lint", + "build-theme": "cunningham -g css,scss,ts -o src/styles && mv src/styles/cunningham-tokens.scss src/styles/cunningham-tokens-sass.scss", + "test": "jest", + "test:watch": "jest --watch" + }, + "engines": { + "node": ">=22.0.0 <25.0.0", + "yarn": "1.22.22" + }, + "dependencies": { + "@gouvfr-lasuite/ui-kit": "0.18.4", + "@openfun/cunningham-react": "4.0.0", + "open-dav-calendar": "*", + "date-fns": "4.1.0", + "@tanstack/react-query": "5.90.10", + "@tanstack/react-table": "8.21.3", + "@viselect/react": "3.9.0", + "clsx": "2.1.1", + "i18next": "25.6.2", + "i18next-browser-languagedetector": "8.2.0", + "next": "15.4.9", + "next-i18next": "15.4.2", + "pretty-bytes": "7.1.0", + "react": "19.2.0", + "react-dom": "19.2.0", + "react-dropzone": "14.3.8", + "react-hook-form": "7.66.0", + "react-i18next": "16.3.3", + "react-toastify": "11.0.5", + "sass": "1.94.0" + }, + "devDependencies": { + "@tanstack/react-query-devtools": "5.66.9", + "@eslint/eslintrc": "3.2.0", + "@tanstack/eslint-plugin-query": "5.66.1", + "@types/jest": "29.5.14", + "@types/node": "24.10.1", + "@types/react": "19.2.5", + "@types/react-dom": "19.2.3", + "eslint": "9.20.1", + "eslint-config-next": "15.1.7", + "jest": "29.7.0", + "ts-jest": "29.2.5", + "typescript": "5.4.5" + } +} diff --git a/src/frontend/apps/calendars/public/assets/401-background.png b/src/frontend/apps/calendars/public/assets/401-background.png new file mode 100644 index 0000000000000000000000000000000000000000..02c7c84df03017bc48d3d81feb6248100c0ad5ae GIT binary patch literal 264501 zcmV)DK*7I>P)F|^00009a7bBm000o2 z000o20Vd5lGynhq0drDELIAGL9O(c600d`2O+f$vv5yP6#bJ(fF$@g$Pvj2XB=@%pc{<_I4OX| zCc4OKR%dloW`w(ko11#_ilcUaYprjeXW{9>#It9@?}_v@v-hqza(`-xI89RuzNM5x zj4|xDzuw;EdHJEw{?x9+{=WL)9^Vgr=Bs?h$C~xNZsomSct4!&RXQuTxxGo3=H>UktL^)r{kGrrbI1Ap-@VIc z;%(0Po4o(F?x~NiBD{_5Q^<%umSfmg0sC#g{q^?!XX0HyBk%heyzTFQ7w7N22EtEy zk-W`g+Xs`|-S*&!{q~`6zl7k3?L&D6-)n0$pM;OKP4`pVUAKYu+kV?``|ZcJ{aWfoTtD?Wud;6+!$a_6h~0Owy^IokmAUQ5xV`PH=404Cl;e9B z`|-BV{Lg*f`(AUukJNpi8_wsQ2Ew;F@b`JszsY{TZbkSeuU z7ghC-oxhJ|{`zCvhqTcA)b=R^>o+~m@8X%?Z$H2N5P0aLL5{3VO~3DLws-XmzR#fk z{q0j)7hbD1`cnsfmnUVvFz>h5-EMnf+Hdc7yK8lp{q}CRSGj)g6j*qdGs68`;oWch z1%JPN=-d7t-ETj%z0bA%7pXP6-}c*n+i&}Azvb z`{!BP8wbMoF@WB0?|<80^ZmBp_S^g3ZaaW~bbf>{Z?8i}-)BCrzggS-Cx8D_`k;4p zE%w)SzungMG2TmWE93aS6WceX!`!B<-8}-0`IhHYtpyfBLdmq%e*1E0~1f(Zs34 zJIksF<2ZV9qR-70ds&qBPkaA_bBymQ{^~oq4|<1x;fLP{dY=fwk5Q%PwzgmDvwACm z@Kre=`>O2Y-tL;~^ZxG{g^!>A*-bW%!yoODiuMhwy8tk4`H=vLVnZ{Z0q_a7`_}ZZ=&=+9XtGzp5I?`Fnpie`#SG; z76{+v`}f=JZa;QCewo)vj|ZwP20D9OhGDXxRoI`S1-lr^GV14}0*tD;DfHbG4vy-u zzV0jt))oxMP+2S+2YpUqQL<|6wH7hUvIyIa1*}60T)V-(s|fvo;92tfN>qY&>IeVX z)ujc-r3KGAhRyXDTKiewW54jds1`>Hk~M=Kf^Ti#vsw2ZS8bn*$j>h=Q12`-A01g> zwSbB5!M@;qI7S5aqWCoA@!r+FyI;RP%q2*ZGzjs!dHC4mr;y5XQg@hnAGI*pZGC1uv$%0^M!DnD# zM6tHMn!<8bGJxWk7R%DAy2MW9I1CoN^s~VNXlp^P>ntE5&{k@7juu>#?b>Jow`mIg ziTH@%i;5Hbi2bka`};nHw#8@IekBFcsxJBa!M;lYwc_iV*7n!-1N&Xs@!)&$dIa{! z_^UwQvTruyrPiOl$pZTBpz7L@y+;98s?zWND7J7_>1)0IBplOV3 z8zQJ72-X#h0$gPQ2%m{|=yuyNAmKk% zrV|4n=7{>-i2<-~EZFW6128H=yj~cn$bg5};_vMu+P)#Mp2s$_HwS_<~-!K-fj_497FpE}Qbu*`n@1h>DQbKwCP`biIg z{onf9T7=1}AFI+3@QT7JHLJi-z2Wzz2MSb7*A_gm`1e*Z)lFa^+}dnzwQOt#H?jqa zwxbn_tjy3t9jAc+76d0$Q>eu7I#zJ@`JDx>g$1pRwL(u$TK-uzF^sH4t!lH^#v-yR z!@Mt7cLL8${H%hXkKm0~ZDLSHfX1=n`w$ROogzrqb;ZDnz=hzq!@SatcenFuwN&f3 zv>D}OpEaTE#3?K=>ntot+Ig_{Zqt-O_#B)|9iQ65fnXh!w%9++Ix(XJ00=?zujY?F z^W1Oy?fctaVr{?ew_Dt>7^AvEC5AvW+P~S#91#$c&EYB!jut2qKqj^Q&H^4HBj#x} z+KvOOxWcQesz5-qR^tu;6l*CWz*u0wV~aqP9NB^ji!;44dIhOgX}1duN^M(u)mHKK zcps6Wg(|NiRtz|OKQa(v-;=W{7<4VL0Dyzwd3e+?s3SPl7D&;;ovYO)s#L2QD;(>{ z;DaDnlo@p@bSYj>z)jcBm1fge#7D(!!5sk_-&+>i-)YK$w`5hT_@)^o_F0v6()9?PHn}pvxVG(4^W+GcQ&Z*EI0w2 zGK~`#e*^&lN)W&{n~qf@f&_ks*&r&gWC0gH&vQstT~XHquS1KqwE%=*!5JNbi3O+R zv8F)V(f(EtS*rOS=9kEzu}_@od5aW*3oX^wsziJ~TECe60hoh8g#Ym9<9k)b>hlo1 z4y^@>&k#Tc6)oDmiNRX|9<9-2$E50+fv*NCcE`Vq(h*rdPqY|utFLUq$AY}H*&P;p093}QXC;PN96q{Zz(dt16et6p{r%veBJvY4 z0+rR)g28H4vzihrbYP{2_qPC+OwsrChTGR!uvzjwBY%hL6_p&?uLv#(rU-rrI`s^Q zi42f9m7N7av@{P8xJOlsNkl{fZqTyCtWuyDwMUC0F#zE+5ZnRAK~TiLpxQ;nhSQ6x zvfB-;2-oW!k16>G5a$#D634c1DhBoy`vNdeAYDXAQ?#KGxb5Y3Yzm%~Fx2e`9rHRb0PQpkP-nY2;M5 znnf`y<=&}ef_RC+jG1~+fVBIq$7p>iFBG{yNqHxfY#8!JA5T8hZ`6>Q6n4F25T%0WZ5 zw`fZRaU3)LUV3$kiVo+3!4$`ViZF?;k=w1TV(s&BErwp7jUc=wnpS~*bx>P!vg2_e z@Z$HPq3rdH-^I3H3;*f%QKCja)C>8c-(Vlh1EBrP|I%WO+Y}WOg3~adWmsBeRj9>j z)!u0Hz7#<>D8s=~p-Ru*r%Ff_*(B)}fI1cUu&sQMu z2j@-{7M&l=R}ozp(A&2!@I6v&}{oU>Q|e)r9Rk2m|9K zJC;?e#UFtU!ECw0!d)=9p_1T3RtS7FdqXtw5p<4S*5p4 zJ3F?P-@CSosjfsvAhF$csq6c&L|YPbPw);0%_S#Pww+bMwdR4E0Y(NmoTC9P$hP5e zA*kY!XJuwV29$_{gPMUT?^jvo8En252z1~}(eq8bx}T~TO$CjxoRpedCVDZ(I-BKS?@>eUQ_q+i(UA%%vZ zQ+gnMS*1lln2Nv0{wZLMd|%Vns(g1n18h+_{R5S*{aJadQYhAvl`h(+!Abo3pR0VW+keXfYWleJFS)?^D-?adH$URDPcXOg&189amF zM|5kgKn#v0wEf2+`j=}4h_>sDZe4dgwwBjSloY7%pqkh9otP}3vc>zs*+f#p87L2O zdI$I9t8JeG@MXX4E5iNu7TaxAmsnJ<5%@~9GHo%h5`$KS|J4fKXrXa|P9tY^o872t zYjP2>IC(2FSv6M9L1(!Xm}Te-Ta*(QQ?yhub4!zgD1yM?z!-cF=86o2VdAV0-#HFw zMG7T}3I(7U?API8O|)eOg0Rgusk&mIMAcM89wS<$*q=3!rLOcsiU*LNZK1iPe+7v06PjfLjmsHrKl(e%xqXatU6meO@v~Yq4FHz5o8E;9 zBs73PC&r;DF!+81`StZqbJN}Ab728%aNU65#WBB+Dsew=`!u$FAlz^7Y114E3m_JJ zER>ujjUy{RR0msIVEbJn0uvj81?E$b6GO!@Ip_pc%yQML6&Qjq_^LqE22>@vS*xvz z3KM|=)r}V18xd->U$@SILt73(g9|nEJeO+SY0=i~s`QzqTB%yVF{48ZPgPXG*P${S zhQh%(lY*kn{h%+3O-R?^M1NINbdm@PqHGyv3SbC4XQ*oNLvb5x5%^1mks^vDPgjaj zK@l@jB^6<&b`We+OOb}bvkG2)t181eK!q%Kj6`%RDmDDO!2cjh&?gUih1$-gTX;n! zFE{O2PY8Oorcu$0yD5$&+s-@nT^m-6iF6q3SS%_j<60f93a)C=M$T5ts=O1< z{`Z4m{`b2Mj(7DvKlZ)v`a7`Qb#hVs&`!LIZQnxprEh8e6LX`ht07!oYLNpFq;4b> zjg}@_m8e2E18XH}y;xZbZ#%O3!OzfItJum!#n7-4K?R6v1v9S{^m(h5s;R51jteao z>dav)z4b`-`6%ECDG&_+9T}Ob#d&!c$<0ISmVCev7(np7m_rc+yRwTN7pdj=K>SLZfqhVWw(pKv0O1n&(Y zd4;9+Cl+i}Xq^Q?wBN+_>z$)lI;lNZOgGi%ZY#AJ&B~Go-N;IbsxxSBHUgHQN>ZQ` z%2kz1VAX?#J7sy86j?c&ws%Q2&5 zb^UjnNtJA`^9clS7BR<+7u|xE;s=>Bqc(8XSKV*>?T5BI3xxaahqq7roF^xCPnM;7 zB^A}qMCEk7-tlL2b?64RN7q-7Koep!xTfYX=1N10F78;o4}b~Ghcw5U=9wT~ACm$o z7D`kt5VnRQ3c8r_CWgL*eiSluq&mt-aL3WH^gtD~)jqwx)?!Y2!=S}jt-gX)>e{}G z4ilZ)s`y@1yEqS!Lla0uK?v2Ysy}_EDkxPq2)JlzDwxZS0znPHmRT956u1b06U^EW z;1w)K23k@a2+R>W6X%KYbA!Mq;3pOyq$iFCitg2L{XH^|04wd#tze_X6aAD^XDnSTpsMgtWjTP?|yk4q8 z>KfqnNOTJIs1>Bib=3S)5^uTUNMRosKh5n;*3@V%jP#)`#QT8!@o)0(3nWTsU%d5p zWCcgTMw#1X`F9la7=#JAbjZ-!E+em8=+f>){t zHVC{iNdk_Vr@hdfXglJ&BnA)}5T%bQQ2?PY1-OwdRd9XL=yV6!KNY15bdLho;NSQz zRizbwmc_dfybg|9|4LIB5=@$@xIz;(C)4Ir9?t+kPY3`ECNvPxZ{d|GRfRX#SvOTNUY_?{tf6;_%pD8lq7Bx*tO)zZVvfa+Iq7su`kx-=w7LaEPsd7YS#i~QC zO;t(=z|B&NDS{+l7t6Vd!oA9tCPc4oAG>Xo%1RQL2JgY~vU2Q%s%#de2mQbR0-a90 z4zs!(s3^$>_XyG$M(6oSx-4dmPa5dL@!kc(ZNGrv%)GnFsRg7YBq`ryBx%T1X`1}? zQh}NIdS&6R8Y5?msH{hCr{cYR@0Fe-JL#Aa1@ggc6IDK{R9uT(_2QgBXH>ISw7@$a z2U?lfQ~4}bPM#NiW8yLEzG6$9BIbcf4pxbN=%tmq66gl|e15iL@&jRT-7C81kB%Gi zGoe8a>d20j?TudTJ9#4Rc&+)6*R~IN?Y&df=#QbSUj8?C>LaWMKjwYEtu2c^YoQim z5VJO!ypF7*klml$w@Sf+6JCd^3^O8{(2D= z-B8<<8k?%Xxp8^I-ay{@(PQ=Atl!wmA_%>Qf-w* z0#u_i-HlG0P-_`g(FT-+wqa|Sq5uTOcu;R6&jZdGjeI9EP+0XXEg0`O`wVl-G}9^M zTbOt}v{@=d-p{Sjz+)EJi9sGH&MES|Vqa%TI;TsFsSjneYMj1`Qpy?qSa0Tn>S5#W z0Mww(JhD|R5rQlXK!hzQFr84ln!84~jM5r|*Ma7OdjnktAY)1G7?d!e(!b4i>AUJ` z{nR@1F23_s*0oQegZJL(6F+tG-X^HL%|+Skn7;aUbIhuYP+44@b>Z~1C18cEy;QiP z!@$Z=nY=87aETWLI;dhn5Sv(46f>zB3qIO+nCq1eQenWER7v7<5R`!OWQ7S*x3|

y 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 P00000NkvXXu0mjfNK|ts literal 0 HcmV?d00001 diff --git a/src/frontend/apps/calendars/public/assets/403-background.png b/src/frontend/apps/calendars/public/assets/403-background.png new file mode 100644 index 0000000000000000000000000000000000000000..480944f344715ccf4634e76957ec71c2e253ff9c GIT binary patch literal 273754 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%0A#SNJLv8pVOz$)sgdp?xPLB*)e%6;pkSPPkY2I(O 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 z

+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 q8g{?g0ssI2000000001he)|T + + + + + + + + + + + + + + + diff --git a/src/frontend/apps/calendars/public/assets/anct_logo_alpha.svg b/src/frontend/apps/calendars/public/assets/anct_logo_alpha.svg new file mode 100644 index 0000000..7d61b61 --- /dev/null +++ b/src/frontend/apps/calendars/public/assets/anct_logo_alpha.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/frontend/apps/calendars/public/assets/anct_logo_beta.svg b/src/frontend/apps/calendars/public/assets/anct_logo_beta.svg new file mode 100644 index 0000000..495e388 --- /dev/null +++ b/src/frontend/apps/calendars/public/assets/anct_logo_beta.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/apps/calendars/public/assets/favicon.png b/src/frontend/apps/calendars/public/assets/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..adf6ce0ac1657838bb656d8c4338466bd96aa13c GIT binary patch literal 670 zcmV;P0%84$P)xdCNC1gj29cIge$3jjGm#R(#~Kqoh#J9Zsbh_WEuz~x`rFoLqkJDosg^YV`p=p8GQz}S9~~u;#a-zUsKdb zMZj@q^S};%fHfgP+WYZk4>eH|@c!<-fiiS}|3p@!V72@Br`EV;N&=4WY#lK;!37~u z24am%LW~?Ob@=d`&d%+-T=>x0`UU1&2n4a`jSV$?pmpx+qe`WK1~157oc=cZtNJJe zj*WybK6Sg^i49(WFr5~CUt1gNLX_L-$cQ+{HN)KU{^lA2NE6e`-lAlmF-C1d5H&Oe!T}(Mzgb=C5z_U~`9s#5arup$;)U|v42rylQLjt^p zh;T+ByHT^nv7jY!xQp=Ek;EyWFls!@iFJ5@AmI~9T>^4D``Ikp-bS#POwx(~yLl%| zo%#rtVJ2xsfB_#aN^~DVVo$wuDgv0*d_Hq)$ literal 0 HcmV?d00001 diff --git a/src/frontend/apps/calendars/public/assets/logo-icon_alpha.svg b/src/frontend/apps/calendars/public/assets/logo-icon_alpha.svg new file mode 100644 index 0000000..ee47c74 --- /dev/null +++ b/src/frontend/apps/calendars/public/assets/logo-icon_alpha.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/frontend/apps/calendars/public/assets/logo-icon_beta.svg b/src/frontend/apps/calendars/public/assets/logo-icon_beta.svg new file mode 100644 index 0000000..55255e6 --- /dev/null +++ b/src/frontend/apps/calendars/public/assets/logo-icon_beta.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/frontend/apps/calendars/public/assets/logo-suite-numerique.png b/src/frontend/apps/calendars/public/assets/logo-suite-numerique.png new file mode 100644 index 0000000000000000000000000000000000000000..840e972e28acc8f035458f05a47ac8d7b0d38385 GIT binary patch literal 11214 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

lxe#sG*51Mvp{8G`Ood9vB~l*1@1nW@1MqmkRF0 z;t=RT^!7)b)6%81?`wjPh8PE8DNJR_pA&8%O1v?{%prtdSMC%dGIX84}w zywAGyY`u-pt6H*ywLg0>c%w|Q*kqhiu(VG!uLa8e{cNF%j|Pj?9aT^8C8M(V{Q)zD zx^p>L8M=YyRaPs;NEgQqwKn&nndbCK-Wth}1za#e8!BJS-;7(y*o|8yt+OO}rKROV@=Gz;c#$XnVa*9JA&>(<^kEo`-cBOwojSR~-Zlsf68hKco3!g{#(p*S2;r9qy zKBoUEdhY)hdbRW^3-2xH-5$Z!*HPJXo|c~2$nc@g+r0+pHNmy)Fr?RsOv)u*OH=g3 zW;zC52tB!_3Fzz4JLBr4>2Y3(6(8Eza+H^J?*~)$#`FWjO zN9pkp<20c-n-!oJM$c22Ypsv5(#Khuw!zdKQkSnWJ8Pc6E>`lN_Reg(aS#Te_$Xs+ zt0UagGyngqgHT*AiE$ExXqfRsAJT=Ii-cAH$O(`VK}WZG*83y#&i_R7)uOJ|!u0xW+@C!;CW=Yx zPxR@5_4M3JX0;bhlwSJ>yPrJ0_O~v*u?zHe-+sR1r+-V?b00C;JF3cm4!8A#Y0~SD z=!qOc8h9nF7S~=-s~^%8p@)YfCQ7Fk$nUwPIh{j!Tvj`6dIO$t0e(KcvFr3Ykzr7# zH;e|T%j8*+5~ zZ;d)}tUSF@nO>#|t(M--Vh=^CR-GR871Q%(Sz>y7FThSQ(}Vx?($TY{y(#5}ImY>{ zMH6#;!PD!irk823ea(s21jB0GkddP9MKffA#3pg-SC<}IO?tUrZD00`&|AyQCi2G+ zaiR(9_$HT#f9E3({(a!Yz3RS)n*K>X$0tH>^kR0jYG5N(SCO3hT$w$=;XyLQ*B+7P zYa67B=>bRn9}tHdF!V|R2=T={s3v@rta1ED(jzWA3GpPA&B!ZhKaR%-8Z*i-m(vg| zOz*1wfK4--U!hTuI@YnMF`<6TqoCNsmR%h^lDYs4X$`VNUKK-fZ3GK@h`VH-Pzp9Q ze}(U{YofQT>0nVXHlsC2qQB@m8iB!_nHw1{=oVR%@ZQ?f+-gng7x*A-OS#nNRg0|- zI?TwAeVS>s_ZGUyz6V=Bo6zN0qvAY@z%7nHrA(=4TCh`qM@8ttz2js79VDMj*>q@g z5d;rs(k~VnE?tf057nHv0n9MVCb2!ZGT3=1!aPTs%w2|FB{Zi5EZ65`!ekjHGO)Q`dG}i!GEGX4{gALDfC1{OdhYH3 zn-f4o93+6F6l#rh=a3{;YoM?1iP3{ad-l|;eLlXV?PAfSmj4xc{Z3cCWDHJ4lc9tR sP?dt$$1+5Rrv7X5SU?DZUjP6A literal 0 HcmV?d00001 diff --git a/src/frontend/apps/calendars/public/assets/logo_alpha.svg b/src/frontend/apps/calendars/public/assets/logo_alpha.svg new file mode 100644 index 0000000..5411eb4 --- /dev/null +++ b/src/frontend/apps/calendars/public/assets/logo_alpha.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/frontend/apps/calendars/public/mime-video.svg b/src/frontend/apps/calendars/public/mime-video.svg new file mode 100644 index 0000000..4196808 --- /dev/null +++ b/src/frontend/apps/calendars/public/mime-video.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/apps/calendars/src/assets/feedback/form.svg b/src/frontend/apps/calendars/src/assets/feedback/form.svg new file mode 100644 index 0000000..6d1caeb --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/feedback/form.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/feedback/tchap.svg b/src/frontend/apps/calendars/src/assets/feedback/tchap.svg new file mode 100644 index 0000000..655df61 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/feedback/tchap.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/feedback/visio.svg b/src/frontend/apps/calendars/src/assets/feedback/visio.svg new file mode 100644 index 0000000..df54fea --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/feedback/visio.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/cancel.svg b/src/frontend/apps/calendars/src/assets/icons/cancel.svg new file mode 100644 index 0000000..3f1832d --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/cancel.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/cancel_blue.svg b/src/frontend/apps/calendars/src/assets/icons/cancel_blue.svg new file mode 100644 index 0000000..b92c720 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/cancel_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/delete_filled.svg b/src/frontend/apps/calendars/src/assets/icons/delete_filled.svg new file mode 100644 index 0000000..2b7fd3f --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/delete_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/info.svg b/src/frontend/apps/calendars/src/assets/icons/info.svg new file mode 100644 index 0000000..e96fa00 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/info.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/settings.svg b/src/frontend/apps/calendars/src/assets/icons/settings.svg new file mode 100644 index 0000000..6dbec58 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/trash.svg b/src/frontend/apps/calendars/src/assets/icons/trash.svg new file mode 100644 index 0000000..2b7fd3f --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/trash.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/undo.svg b/src/frontend/apps/calendars/src/assets/icons/undo.svg new file mode 100644 index 0000000..6549735 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/undo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/icons/undo_blue.svg b/src/frontend/apps/calendars/src/assets/icons/undo_blue.svg new file mode 100644 index 0000000..a1effc4 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/icons/undo_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/frontend/apps/calendars/src/assets/logo-gouv.svg b/src/frontend/apps/calendars/src/assets/logo-gouv.svg new file mode 100644 index 0000000..824e1b9 --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/logo-gouv.svg @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/frontend/apps/calendars/src/assets/logo-icon.svg b/src/frontend/apps/calendars/src/assets/logo-icon.svg new file mode 100644 index 0000000..6afd48a --- /dev/null +++ b/src/frontend/apps/calendars/src/assets/logo-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/frontend/apps/calendars/src/features/analytics/AnalyticsProvider.tsx b/src/frontend/apps/calendars/src/features/analytics/AnalyticsProvider.tsx new file mode 100644 index 0000000..6869518 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/analytics/AnalyticsProvider.tsx @@ -0,0 +1,7 @@ +export const AnalyticsProvider = ({ + children, +}: { + children: React.ReactNode; +}) => { + return <>{children}; +}; diff --git a/src/frontend/apps/calendars/src/features/api/APIError.ts b/src/frontend/apps/calendars/src/features/api/APIError.ts new file mode 100644 index 0000000..8942ebf --- /dev/null +++ b/src/frontend/apps/calendars/src/features/api/APIError.ts @@ -0,0 +1,57 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import i18n from "@/features/i18n/initI18n"; +import { AppError } from "../errors/AppError"; + +export class APIError extends Error { + data?: any; + code: number; + + constructor(code: number, data?: any) { + super(); + this.data = data; + this.code = code; + } +} + +export const errorToString = (error: unknown): string => { + if (typeof error === "string") { + return error; + } + + if (error instanceof APIError) { + const data = error.data; + // If there is a data, it means that the error is a JSON object + if (typeof data === "string") { + return data; + } + + if ( + data?.errors && + Array.isArray(data?.errors) && + data?.errors?.length > 0 + ) { + return data.errors[0].detail; + } + + if (data) { + /** + * This is made to handle full text errors from the API like: + * + * "title": [ + * "The title field is required." + * ] + */ + return Object.entries(error.data) + .map(([, value]) => `${value}`) + .join("\n"); + } + // If there is no data, it means that the error is a string, probably a complicated html error. + return i18n.t("api.error.unexpected"); + } + // We want to show the error message from the AppError only. Not message from the Error class as they + // can be really technical and not helpful for the user. For those we show the generic error message. + if (error instanceof AppError) { + return error.message; + } + return i18n.t("api.error.unexpected"); +}; diff --git a/src/frontend/apps/calendars/src/features/api/fetchApi.ts b/src/frontend/apps/calendars/src/features/api/fetchApi.ts new file mode 100644 index 0000000..d61c570 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/api/fetchApi.ts @@ -0,0 +1,67 @@ +import { baseApiUrl, isJson } from "./utils"; +import { APIError } from "./APIError"; + +/** + * Retrieves the CSRF token from the document's cookies. + * + * @returns {string|null} The CSRF token if found in the cookies, or null if not present. + */ +function getCSRFToken() { + return document.cookie + .split(";") + .filter((cookie) => cookie.trim().startsWith("csrftoken=")) + .map((cookie) => cookie.split("=")[1]) + .pop(); +} + +export const SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL = + "redirect_after_login_url"; + +const redirect = (url: string, saveRedirectAfterLoginUrl = true) => { + if (saveRedirectAfterLoginUrl) { + sessionStorage.setItem( + SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL, + window.location.href + ); + } + window.location.href = url; +}; + +export interface fetchAPIOptions { +} + +export const fetchAPI = async ( + input: string, + init?: RequestInit & { params?: Record }, + options?: fetchAPIOptions +) => { + const apiUrl = new URL(`${baseApiUrl("1.0")}${input}`); + if (init?.params) { + Object.entries(init.params).forEach(([key, value]) => { + apiUrl.searchParams.set(key, String(value)); + }); + } + const csrfToken = getCSRFToken(); + + const response = await fetch(apiUrl, { + ...init, + credentials: "include", + headers: { + ...init?.headers, + "Content-Type": "application/json", + ...(csrfToken && { "X-CSRFToken": csrfToken }), + }, + }); + + if (response.ok) { + return response; + } + + const data = await response.text(); + + if (isJson(data)) { + throw new APIError(response.status, JSON.parse(data)); + } + + throw new APIError(response.status); +}; diff --git a/src/frontend/apps/calendars/src/features/api/types.ts b/src/frontend/apps/calendars/src/features/api/types.ts new file mode 100644 index 0000000..a181a2b --- /dev/null +++ b/src/frontend/apps/calendars/src/features/api/types.ts @@ -0,0 +1,18 @@ +export interface ApiConfig { + FRONTEND_THEME?: string; + FRONTEND_HIDE_GAUFRE?: boolean; + FRONTEND_FEEDBACK_BUTTON_SHOW?: boolean; + FRONTEND_FEEDBACK_BUTTON_IDLE?: boolean; + FRONTEND_FEEDBACK_ITEMS?: Record; + FRONTEND_MORE_LINK?: string; + FRONTEND_FEEDBACK_MESSAGES_WIDGET_API_URL?: string; + FRONTEND_FEEDBACK_MESSAGES_WIDGET_PATH?: string; + FRONTEND_FEEDBACK_MESSAGES_WIDGET_CHANNEL?: string; + theme_customization?: ThemeCustomization; +} + +export interface ThemeCustomization { + footer?: Record; + [key: string]: unknown; +} + diff --git a/src/frontend/apps/calendars/src/features/api/utils.ts b/src/frontend/apps/calendars/src/features/api/utils.ts new file mode 100644 index 0000000..29838db --- /dev/null +++ b/src/frontend/apps/calendars/src/features/api/utils.ts @@ -0,0 +1,39 @@ +export const errorCauses = async (response: Response, data?: unknown) => { + const errorsBody = (await response.json()) as Record< + string, + string | string[] + > | null; + + const causes = errorsBody + ? Object.entries(errorsBody) + .map(([, value]) => value) + .flat() + : undefined; + + return { + status: response.status, + cause: causes, + data, + }; +}; + +export const getOrigin = () => { + return ( + process.env.NEXT_PUBLIC_API_ORIGIN || + (typeof window !== "undefined" ? window.location.origin : "") + ); +}; +export const baseApiUrl = (apiVersion: string = "1.0") => { + const origin = getOrigin(); + return `${origin}/api/v${apiVersion}/`; +}; + +export const isJson = (str: string) => { + try { + JSON.parse(str); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + return false; + } + return true; +}; diff --git a/src/frontend/apps/calendars/src/features/auth/Auth.tsx b/src/frontend/apps/calendars/src/features/auth/Auth.tsx new file mode 100644 index 0000000..24f34f3 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/auth/Auth.tsx @@ -0,0 +1,76 @@ +import React, { PropsWithChildren, useEffect, useState } from "react"; + +import { fetchAPI } from "@/features/api/fetchApi"; +import { User } from "@/features/auth/types"; +import { baseApiUrl } from "../api/utils"; +import { APIError } from "../api/APIError"; +import { SpinnerPage } from "@/features/ui/components/spinner/SpinnerPage"; + +export const logout = () => { + window.location.replace(new URL("logout/", baseApiUrl()).href); +}; + +export const login = (returnTo?: string) => { + const url = new URL("authenticate/", baseApiUrl()); + if (returnTo) { + url.searchParams.set("returnTo", returnTo); + } + window.location.replace(url.href); +}; + +interface AuthContextInterface { + user?: User | null; + init?: () => Promise; + refreshUser?: () => Promise; +} + +export const AuthContext = React.createContext({}); + +export const useAuth = () => React.useContext(AuthContext); + +export const Auth = ({ + children, + redirect, +}: PropsWithChildren & { redirect?: boolean }) => { + const [user, setUser] = useState(); + + const init = async () => { + try { + const response = await fetchAPI(`users/me/`); + const data = (await response.json()) as User; + setUser(data); + return data; + } catch (error) { + if (redirect && error instanceof APIError && error.code === 401) { + login(); + } else { + setUser(null); + } + return null; + } + }; + + const refreshUser = async () => { + void init(); + }; + + useEffect(() => { + void init(); + }, []); + + if (user === undefined) { + return ; + } + + return ( + + {children} + + ); +}; diff --git a/src/frontend/apps/calendars/src/features/auth/components/LoginButton.tsx b/src/frontend/apps/calendars/src/features/auth/components/LoginButton.tsx new file mode 100644 index 0000000..e0ac806 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/auth/components/LoginButton.tsx @@ -0,0 +1,23 @@ +import { Button } from "@openfun/cunningham-react"; +import { login } from "../Auth"; +import { useTranslation } from "react-i18next"; +import { SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL } from "@/features/api/fetchApi"; + +export const LoginButton = () => { + const { t } = useTranslation(); + return ( + + ); +}; diff --git a/src/frontend/apps/calendars/src/features/auth/components/LogoutButton.tsx b/src/frontend/apps/calendars/src/features/auth/components/LogoutButton.tsx new file mode 100644 index 0000000..145e86e --- /dev/null +++ b/src/frontend/apps/calendars/src/features/auth/components/LogoutButton.tsx @@ -0,0 +1,12 @@ +import { Button } from "@openfun/cunningham-react"; +import { logout } from "../Auth"; +import { useTranslation } from "react-i18next"; + +export const LogoutButton = () => { + const { t } = useTranslation(); + return ( + + ); +}; diff --git a/src/frontend/apps/calendars/src/features/auth/types.ts b/src/frontend/apps/calendars/src/features/auth/types.ts new file mode 100644 index 0000000..29093fc --- /dev/null +++ b/src/frontend/apps/calendars/src/features/auth/types.ts @@ -0,0 +1,12 @@ +/** + * Represents user retrieved from the API. + * @interface User + * @property {string} id - The id of the user. + * @property {string} email - The email of the user. + * @property {string} name - The name of the user. + */ +export interface User { + id: string; + email: string; + language: string; +} diff --git a/src/frontend/apps/calendars/src/features/calendar/api.ts b/src/frontend/apps/calendars/src/features/calendar/api.ts new file mode 100644 index 0000000..62c6799 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/api.ts @@ -0,0 +1,51 @@ +/** + * API functions for calendar operations. + */ + +import { fetchAPI } from "@/features/api/fetchApi"; + +export interface Calendar { + id: string; + name: string; + color: string; + description: string; + is_default: boolean; + is_visible: boolean; + owner: string; +} + + +/** + * Fetch all calendars accessible by the current user. + */ +export const getCalendars = async (): Promise => { + const response = await fetchAPI("calendars/"); + return response.json(); +}; + +/** + * Create a new calendar. + */ +export const createCalendar = async (data: { + name: string; + color?: string; +}): Promise => { + const response = await fetchAPI("calendars/", { + method: "POST", + body: JSON.stringify(data), + }); + return response.json(); +}; + +/** + * Toggle calendar visibility. + */ +export const toggleCalendarVisibility = async ( + calendarId: string +): Promise<{ is_visible: boolean }> => { + const response = await fetchAPI(`calendars/${calendarId}/toggle_visibility/`, { + method: "PATCH", + }); + return response.json(); +}; + diff --git a/src/frontend/apps/calendars/src/features/calendar/components/CalendarList.scss b/src/frontend/apps/calendars/src/features/calendar/components/CalendarList.scss new file mode 100644 index 0000000..c960800 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/CalendarList.scss @@ -0,0 +1,99 @@ +.calendar-list { + padding: 0.5rem 0.75rem; + + &__section { + margin-bottom: 1rem; + } + + &__section-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.5rem; + } + + &__section-title { + font-size: 0.75rem; + font-weight: 600; + color: var(--c--theme--colors--greyscale-600); + text-transform: uppercase; + letter-spacing: 0.025em; + } + + &__add-btn { + display: flex; + align-items: center; + justify-content: center; + width: 1.5rem; + height: 1.5rem; + border: none; + background: transparent; + border-radius: 50%; + cursor: pointer; + color: var(--c--theme--colors--greyscale-600); + transition: background-color 0.15s, color 0.15s; + + &:hover { + background-color: var(--c--theme--colors--greyscale-100); + color: var(--c--theme--colors--primary-500); + } + + .material-icons { + font-size: 1.125rem; + } + } + + &__items { + display: flex; + flex-direction: column; + gap: 0.25rem; + } + + &__item { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.375rem 0.25rem; + border-radius: 4px; + transition: background-color 0.15s; + + &:hover { + background-color: var(--c--theme--colors--greyscale-50); + } + + // Override Cunningham checkbox styles for compact display + .c__checkbox { + margin: 0; + } + + .c__checkbox__multi-wrapper { + gap: 0; + } + } + + &__color { + width: 0.75rem; + height: 0.75rem; + border-radius: 2px; + flex-shrink: 0; + } + + &__name { + flex: 1; + font-size: 0.875rem; + color: var(--c--theme--colors--greyscale-800); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &__badge { + font-size: 0.625rem; + padding: 0.125rem 0.375rem; + background-color: var(--c--theme--colors--greyscale-100); + color: var(--c--theme--colors--greyscale-600); + border-radius: 0.75rem; + text-transform: uppercase; + font-weight: 500; + } +} diff --git a/src/frontend/apps/calendars/src/features/calendar/components/CalendarList.tsx b/src/frontend/apps/calendars/src/features/calendar/components/CalendarList.tsx new file mode 100644 index 0000000..4554657 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/CalendarList.tsx @@ -0,0 +1,88 @@ +/** + * CalendarList component - List of calendars with visibility toggles. + */ + +import { Button, Checkbox } from "@openfun/cunningham-react"; + +import { Calendar } from "../api"; +import { useToggleCalendarVisibility } from "../hooks/useCalendars"; + +interface CalendarListProps { + calendars: Calendar[]; + onCreateCalendar: () => void; +} + +export const CalendarList = ({ + calendars, + onCreateCalendar, +}: CalendarListProps) => { + const toggleVisibility = useToggleCalendarVisibility(); + + // Ensure calendars is an array + const calendarsArray = Array.isArray(calendars) ? calendars : []; + + const ownedCalendars = calendarsArray.filter( + (cal) => !cal.name.includes("(partagé)") + ); + const sharedCalendars = calendarsArray.filter((cal) => + cal.name.includes("(partagé)") + ); + + const handleToggle = (calendarId: string) => { + toggleVisibility.mutate(calendarId); + }; + + const renderCalendarItem = (calendar: Calendar) => ( +

+ ); + + return ( +
+
+
+ Mes calendriers + +
+
+ {ownedCalendars.map(renderCalendarItem)} +
+
+ + {sharedCalendars.length > 0 && ( +
+
+ + Calendriers partagés + +
+
+ {sharedCalendars.map(renderCalendarItem)} +
+
+ )} +
+ ); +}; diff --git a/src/frontend/apps/calendars/src/features/calendar/components/CalendarView.scss b/src/frontend/apps/calendars/src/features/calendar/components/CalendarView.scss new file mode 100644 index 0000000..c5646fe --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/CalendarView.scss @@ -0,0 +1,171 @@ +.calendar-view { + display: flex; + flex-direction: column; + flex: 1; + height: 100%; + min-height: 0; + position: relative; + + &__loading { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem 2rem; + background: var(--c--theme--colors--greyscale-000); + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + + p { + margin: 0; + color: var(--c--theme--colors--greyscale-600); + } + } + + &__container { + flex: 1; + min-height: 0; + overflow: hidden; + transition: opacity 0.3s ease; + } + + &--loading, + &--error { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + gap: 1rem; + padding: 2rem; + text-align: center; + + p { + color: var(--c--theme--colors--greyscale-600); + margin: 0; + } + + button { + padding: 0.5rem 1rem; + background: var(--c--theme--colors--primary-500); + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + + &:hover { + background: var(--c--theme--colors--primary-600); + } + } + } +} + +// Open-calendar overrides to match La Suite theme +.calendar-view__container { + // Calendar toolbar + .ec-toolbar { + padding: 0.75rem 1rem; + border-bottom: 1px solid var(--c--theme--colors--greyscale-200); + background: var(--c--theme--colors--greyscale-000); + } + + // Today button + .ec-button { + padding: 0.375rem 0.75rem; + border-radius: 4px; + font-size: 0.875rem; + font-weight: 500; + border: 1px solid var(--c--theme--colors--greyscale-300); + background: var(--c--theme--colors--greyscale-000); + color: var(--c--theme--colors--greyscale-800); + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + background: var(--c--theme--colors--greyscale-100); + } + + &.ec-active { + background: var(--c--theme--colors--primary-500); + border-color: var(--c--theme--colors--primary-500); + color: white; + } + } + + // Navigation buttons + .ec-prev, + .ec-next { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + } + + // Title + .ec-title { + font-size: 1.125rem; + font-weight: 600; + color: var(--c--theme--colors--greyscale-900); + text-transform: capitalize; + } + + // Days header + .ec-days, + .ec-day { + border-color: var(--c--theme--colors--greyscale-200); + } + + .ec-day-head { + padding: 0.5rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + color: var(--c--theme--colors--greyscale-600); + } + + // Time slots + .ec-time { + font-size: 0.75rem; + color: var(--c--theme--colors--greyscale-500); + } + + // Events + .ec-event { + border-radius: 4px; + font-size: 0.75rem; + padding: 2px 4px; + border: none; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + + &:hover { + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); + } + } + + // Today highlight + .ec-today { + background: rgba(var(--c--theme--colors--primary-rgb, 49, 116, 173), 0.1); + } + + // Now indicator + .ec-now-indicator { + border-color: var(--c--theme--colors--danger-500); + + &::before { + background: var(--c--theme--colors--danger-500); + } + } + + // Popup styles + .ec-popup { + border-radius: 8px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + border: 1px solid var(--c--theme--colors--greyscale-200); + } +} diff --git a/src/frontend/apps/calendars/src/features/calendar/components/CalendarView.tsx b/src/frontend/apps/calendars/src/features/calendar/components/CalendarView.tsx new file mode 100644 index 0000000..e7603e9 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/CalendarView.tsx @@ -0,0 +1,209 @@ +/** + * CalendarView component using open-calendar (Algoo). + * Renders a CalDAV-connected calendar view. + */ + +import { useEffect, useRef, useState } from "react"; + +import { useAuth } from "@/features/auth/Auth"; +import { createEventModalHandlers, type ModalState } from "./EventModalAdapter"; +import { useEventModal } from "../hooks/useEventModal"; +import type { IcsEvent } from 'ts-ics'; + +interface CalendarViewProps { + selectedDate?: Date; + onSelectDate?: (date: Date) => void; +} + +export const CalendarView = ({ + selectedDate = new Date(), + onSelectDate, +}: CalendarViewProps) => { + const containerRef = useRef(null); + const calendarRef = useRef(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [modalState, setModalState] = useState({ + isOpen: false, + mode: 'create', + event: null, + calendarUrl: '', + calendars: [], + handleSave: null, + handleDelete: null, + }); + const { user } = useAuth(); + + // Use the modal hook with state from adapter + const modal = useEventModal({ + calendars: modalState.calendars, + initialEvent: modalState.event, + initialCalendarUrl: modalState.calendarUrl, + onSubmit: async (event: IcsEvent, calendarUrl: string) => { + if (modalState.handleSave) { + await modalState.handleSave({ calendarUrl, event }); + setModalState(prev => ({ ...prev, isOpen: false })); + } + }, + onDelete: async (event: IcsEvent, calendarUrl: string) => { + if (modalState.handleDelete) { + await modalState.handleDelete({ calendarUrl, event }); + setModalState(prev => ({ ...prev, isOpen: false })); + } + }, + }); + + // Sync modal state with adapter state + useEffect(() => { + if (modalState.isOpen) { + // Always call open to update all state (event, mode, calendarUrl, calendars) + modal.open(modalState.event, modalState.mode, modalState.calendarUrl, modalState.calendars); + } else if (modal.isOpen) { + modal.close(); + } + }, [modalState.isOpen, modalState.event, modalState.mode, modalState.calendarUrl, modalState.calendars]); + + useEffect(() => { + const initCalendar = async () => { + if (!containerRef.current || !user) return; + + try { + setIsLoading(true); + setError(null); + + // Dynamically import open-calendar to avoid SSR issues (uses browser-only globals) + const { createCalendar } = await import("open-dav-calendar"); + + // Clear previous calendar instance + if (containerRef.current) { + containerRef.current.innerHTML = ""; + } + + // CalDAV server URL - proxied through Django backend + // The proxy handles authentication via session cookies + // open-calendar will discover calendars from this URL + const caldavServerUrl = `${process.env.NEXT_PUBLIC_API_ORIGIN}/api/v1.0/caldav/`; + + // Create calendar with CalDAV source + // Use fetchOptions with credentials to include cookies + const calendar = await createCalendar( + [ + { + serverUrl: caldavServerUrl, + fetchOptions: { + credentials: "include" as RequestCredentials, + headers: { + "Content-Type": "application/xml", + }, + }, + }, + ], + [], // No address books for now + containerRef.current, + { + view: "timeGridWeek", + views: ["dayGridMonth", "timeGridWeek", "timeGridDay", "listWeek"], + locale: "fr", + date: selectedDate, + editable: true, + // Use custom EventEditHandlers that update React state + ...createEventModalHandlers(setModalState, []), + onEventCreated: (info) => { + console.log("Event created:", info); + }, + onEventUpdated: (info) => { + console.log("Event updated:", info); + }, + onEventDeleted: (info) => { + console.log("Event deleted:", info); + }, + }, + { + // French translations + calendar: { + today: "Aujourd'hui", + month: "Mois", + week: "Semaine", + day: "Jour", + list: "Liste", + }, + event: { + edit: "Modifier", + delete: "Supprimer", + save: "Enregistrer", + cancel: "Annuler", + title: "Titre", + description: "Description", + location: "Lieu", + startDate: "Date de début", + endDate: "Date de fin", + allDay: "Journée entière", + }, + } + ); + + calendarRef.current = calendar; + setIsLoading(false); + } catch (err) { + console.error("Failed to initialize calendar:", err); + setError( + err instanceof Error + ? err.message + : "Erreur lors du chargement du calendrier" + ); + setIsLoading(false); + } + }; + + initCalendar(); + + return () => { + // Cleanup + if (containerRef.current) { + containerRef.current.innerHTML = ""; + } + calendarRef.current = null; + }; + }, [user]); + + // Update calendar date when selectedDate changes + useEffect(() => { + if (calendarRef.current && selectedDate) { + // open-calendar may have a method to set date + // This depends on the CalendarElement API + } + }, [selectedDate]); + + if (!user) { + return ( +
+

Connexion requise pour afficher le calendrier

+
+ ); + } + + if (error) { + return ( +
+

{error}

+ +
+ ); + } + + return ( +
+ {isLoading && ( +
+

Chargement du calendrier...

+
+ )} +
+ {modal.Modal} +
+ ); +}; diff --git a/src/frontend/apps/calendars/src/features/calendar/components/CreateCalendarModal.tsx b/src/frontend/apps/calendars/src/features/calendar/components/CreateCalendarModal.tsx new file mode 100644 index 0000000..04c2b8c --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/CreateCalendarModal.tsx @@ -0,0 +1,112 @@ +/** + * Modal component for creating a new calendar. + */ + +import { useState, useEffect } from "react"; +import { + Button, + Input, + Modal, + ModalSize, + useModal, +} from "@openfun/cunningham-react"; +import { useTranslation } from "next-i18next"; +import { useCreateCalendar } from "../hooks/useCalendars"; +import { addToast, ToasterItem } from "@/features/ui/components/toaster/Toaster"; +import { errorToString } from "@/features/api/APIError"; + +export const useCreateCalendarModal = () => { + const { t } = useTranslation(); + const modal = useModal(); + const createCalendar = useCreateCalendar(); + const [name, setName] = useState(""); + const [isSubmitting, setIsSubmitting] = useState(false); + + // Reset form when modal opens + useEffect(() => { + if (modal.isOpen) { + setName(""); + setIsSubmitting(false); + } + }, [modal.isOpen]); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!name.trim()) { + return; + } + + setIsSubmitting(true); + try { + await createCalendar.mutateAsync({ + name: name.trim(), + }); + addToast( + + {t("calendar.created_success", { name: name.trim(), defaultValue: `Calendrier "${name.trim()}" créé avec succès` })} + + ); + setName(""); + modal.close(); + } catch (error) { + console.error("Failed to create calendar:", error); + const errorMessage = errorToString(error); + addToast( + + {errorMessage || t("calendar.created_error", { defaultValue: "Erreur lors de la création du calendrier" })} + + ); + } finally { + setIsSubmitting(false); + } + }; + + const handleClose = () => { + setName(""); + modal.close(); + }; + + return { + ...modal, + Modal: ( + +
+ ) => setName(e.target.value)} + required + disabled={isSubmitting} + autoFocus + placeholder={t("calendar.create_modal.name_placeholder", { defaultValue: "Mon calendrier" })} + /> +
+ + +
+
+
+ ), + }; +}; diff --git a/src/frontend/apps/calendars/src/features/calendar/components/EventModal.scss b/src/frontend/apps/calendars/src/features/calendar/components/EventModal.scss new file mode 100644 index 0000000..381a78b --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/EventModal.scss @@ -0,0 +1,90 @@ +.event-modal { + &__feature-tag { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1rem; + border-radius: 2rem; + border: none; + background: #f1f3f4; + color: #5f6368; + cursor: pointer; + font-size: 0.875rem; + transition: background-color 0.15s, color 0.15s; + + &:hover { + background: #e8eaeb; + } + + &--active { + background: #e8f0fe; + color: #1a73e8; + + &:hover { + background: #d2e3fc; + } + } + + .material-icons { + font-size: 1.125rem; + } + } +} + +// Utility classes for layout +.event-modal-layout { + display: flex; + flex-direction: column; + + &--row { + flex-direction: row; + } + + &--wrap { + flex-wrap: wrap; + } + + &--justify-space-between { + justify-content: space-between; + } + + &--align-center { + align-items: center; + } + + &--flex-1 { + flex: 1; + } + + &--gap-2rem { + gap: 2rem; + } + + &--gap-1rem { + gap: 1rem; + } + + &--gap-0-5rem { + gap: 0.5rem; + } + + &--margin-bottom-1rem { + margin-bottom: 1rem; + } + + &--margin-top-2rem { + margin-top: 2rem; + } + + &--margin-left-auto { + margin-left: auto; + } + + &--margin-left-2rem { + margin-left: 2rem; + } + + &--margin-top-0-5rem { + margin-top: 0.5rem; + } +} diff --git a/src/frontend/apps/calendars/src/features/calendar/components/EventModal.tsx b/src/frontend/apps/calendars/src/features/calendar/components/EventModal.tsx new file mode 100644 index 0000000..cc904f6 --- /dev/null +++ b/src/frontend/apps/calendars/src/features/calendar/components/EventModal.tsx @@ -0,0 +1,441 @@ +import { Modal, Button, Input, TextArea, Select } from '@openfun/cunningham-react'; +import type { IcsEvent, IcsRecurrenceRule } from 'ts-ics'; +import { useState, useEffect, useRef } from "react"; +import { RecurrenceEditor } from './RecurrenceEditor'; + +// Helper function to check if event is all-day (same logic as open-dav-calendar) +function isEventAllDay(event: IcsEvent): boolean { + return event.start.type === 'DATE' || (event.end?.type === 'DATE'); +} + +// Calendar type from open-calendar (exported for use in other components) +export interface Calendar { + url: string; + uid?: unknown; + displayName?: string; + calendarColor?: string; + description?: string; +} + +interface EventModalProps { + isOpen: boolean; + mode: 'create' | 'edit'; + calendars: Calendar[]; + selectedEvent?: IcsEvent | null; + calendarUrl: string; + onSubmit: (event: IcsEvent, calendarUrl: string) => Promise; + onAllDayChange: (isAllDay: boolean) => void; + onClose: () => void; + onDelete?: (event: IcsEvent, calendarUrl: string) => Promise; +} + +const VISIBILITY_OPTIONS = [ + { value: 'default', label: 'Par défaut' }, + { value: 'public', label: 'Public' }, + { value: 'private', label: 'Privé' }, +] as const; + +export function EventModal({ + isOpen, + mode, + calendars, + selectedEvent, + calendarUrl, + onSubmit, + onAllDayChange, + onClose, + onDelete, +}: EventModalProps) { + const titleInputRef = useRef(null); + const [formData, setFormData] = useState>({}); + const [activeFeatures, setActiveFeatures] = useState>(new Set()); + const [selectedCalendarUrl, setSelectedCalendarUrl] = useState(calendarUrl); + const [allDay, setAllDay] = useState(false); + + // Helper to get local date from IcsDateObject + const getLocalDate = (dateObj: { date: Date; local?: { date: Date; timezone: string } }): Date => { + return dateObj.local?.date || dateObj.date; + }; + + // Format date for input + const formatDateForInput = (date: Date): string => { + return date.toISOString().split('T')[0]; + }; + + // Format time for input + const formatTimeForInput = (date: Date): string => { + return date.toTimeString().slice(0, 5); + }; + + useEffect(() => { + if (selectedEvent) { + const eventAllDay = isEventAllDay(selectedEvent); + const startDate = getLocalDate(selectedEvent.start); + const endDate = selectedEvent.end ? getLocalDate(selectedEvent.end) : startDate; + + setAllDay(eventAllDay); + setFormData({ + ...selectedEvent, + summary: selectedEvent.summary || '', + startTime: eventAllDay ? undefined : formatTimeForInput(startDate), + endTime: eventAllDay ? undefined : formatTimeForInput(endDate), + }); + setSelectedCalendarUrl(calendarUrl); + } else { + const now = new Date(); + const endTime = new Date(now.getTime() + 30 * 60 * 1000); + setAllDay(false); + setFormData({ + summary: '', + start: { + type: 'DATE-TIME', + date: now, + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }, + end: { + type: 'DATE-TIME', + date: endTime, + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }, + startTime: formatTimeForInput(now), + endTime: formatTimeForInput(endTime), + }); + setSelectedCalendarUrl(calendars[0]?.url || ''); + } + }, [selectedEvent, calendars, calendarUrl]); + + useEffect(() => { + if (isOpen) { + requestAnimationFrame(() => { + titleInputRef.current?.focus(); + }); + } + }, [isOpen]); + + const startDate = formData.start ? getLocalDate(formData.start) : new Date(); + const endDate = formData.end ? getLocalDate(formData.end) : startDate; + + const toggleFeature = (feature: string) => { + if (feature === 'allDay') { + const newAllDay = !allDay; + setAllDay(newAllDay); + onAllDayChange(newAllDay); + return; + } + + setActiveFeatures(prev => { + const next = new Set(prev); + if (next.has(feature)) { + next.delete(feature); + } else { + next.add(feature); + } + return next; + }); + }; + + const handleSubmit = async () => { + if (!formData.summary) return; + + const startDateValue = new Date(`${formatDateForInput(startDate)}T${allDay ? '00:00:00' : formData.startTime || '00:00:00'}`); + const endDateValue = new Date(`${formatDateForInput(endDate)}T${allDay ? '00:00:00' : formData.endTime || '00:00:00'}`); + + const updatedEvent: IcsEvent = { + ...(selectedEvent || {}), + uid: selectedEvent?.uid || `event-${Date.now()}`, + summary: formData.summary || '', + location: formData.location || undefined, + description: formData.description || formData.notes || undefined, + start: { + type: allDay ? 'DATE' : 'DATE-TIME', + date: startDateValue, + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }, + end: { + type: allDay ? 'DATE' : 'DATE-TIME', + date: endDateValue, + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + }, + recurrenceRule: formData.recurrenceRule, + }; + + await onSubmit(updatedEvent, selectedCalendarUrl); + }; + + const renderFeatureContent = () => { + return ( + <> + {activeFeatures.has('calendar') && ( +
+ setFormData(prev => ({ ...prev, location: e.target.value }))} + icon={location_on} + /> +
+ )} + + {activeFeatures.has('notes') && ( +
+ +
+
+ + +
+
+ + + +
+` + +const calendarsHtml = /*html*/` + +{{#calendars}} + +{{/calendars}}` + +const mailboxesHtml = /*html*/` +{{#mailboxes}} + +{{/mailboxes}}` + +const attendeeHtml = /*html*/` +
+ + + + +
` + +export class EventEditPopup { + + private _recurringPopup: RecurringEventPopup + private _popup: Popup + private _form: HTMLFormElement + private _calendar: HTMLSelectElement + private _mailboxes: HTMLDataListElement + private _attendees: HTMLDivElement + private _rruleUnchanged: HTMLOptionElement + + private _hideVCardEmails?: boolean + private _vCardContacts: VCard[] = [] + private _eventContacts: Contact[] = [] + + private _event?: IcsEvent + private _userContact?: Contact + private _calendarUrl?: string + private _handleSave: EventEditCallback | null = null + private _handleDelete: EventEditCallback | null = null + + public constructor(target: Node, options: DefaultComponentsOptions) { + this._hideVCardEmails = options.hideVCardEmails + const timezones = tzlib_get_timezones() as string[] + + this._recurringPopup = new RecurringEventPopup(target) + + this._popup = new Popup(target) + this._form = parseHtml(html, { + t: getTranslations().eventForm, + trrules: getTranslations().rrules, + timezones: timezones, + rrules: namedRRules.map(rule => ({ rule, label: getTranslations().rrules[rule] })), + userParticipationStatuses: attendeeUserParticipationStatusTypes.map(stat => ({ + key: stat, + translation: getTranslations().userParticipationStatus[stat], + })), + })[0] + this._popup.content.appendChild(this._form) + + this._calendar = this._form.querySelector('.open-calendar__form__content [name="calendar"]')! + this._mailboxes = this._form.querySelector('#open-calendar__event-edit__mailboxes')! + this._attendees = this._form.querySelector( + '.open-calendar__event-edit__attendees > .open-calendar__form__list', + )! + const allday = this._form.querySelector('.open-calendar__event-edit [name="allday"]')! + const addAttendee = this._form.querySelector('.open-calendar__event-edit__attendees > button')! + this._rruleUnchanged = this._form.querySelector('.open-calendar__event-edit__rrule__unchanged')! + const cancel = this._form.querySelector('.open-calendar__form__buttons [name="cancel"]')! + const remove = this._form.querySelector('.open-calendar__form__buttons [name="delete"]')! + + this._form.addEventListener('submit', async (e) => { e.preventDefault(); await this.save() }) + allday.addEventListener('click', this.updateAllday) + addAttendee.addEventListener('click', () => this.addAttendee({ email: '' })) + cancel.addEventListener('click', this.cancel) + remove.addEventListener('click', this.delete) + } + + public destroy = () => { + this._form.remove() + } + + private setCalendars = (calendars: Calendar[]) => { + const calendarElements = parseHtml(calendarsHtml, { + calendars, + t: getTranslations().eventForm, + }) + this._calendar.innerHTML = '' + this._calendar.append(...Array.from(calendarElements)) + } + + private setContacts = (vCardContacts: VCard[], eventContacts: Contact[]) => { + this._vCardContacts = [] + for (const contact of vCardContacts) { + if (this._vCardContacts.find(c => isSameContact(c, contact))) continue + this._vCardContacts.push(contact) + } + for (const contact of eventContacts) { + if (this._vCardContacts.find(c => isSameContact(c, contact))) continue + if (this._eventContacts.find(c => isSameContact(c, contact))) continue + this._eventContacts.push(contact) + } + const mailboxesElement = parseHtml(mailboxesHtml, { + mailboxes: [ + ...this._vCardContacts.map(c => this.getValueFromVCard(c)), + ...this._eventContacts.map(c => this.getValueFromContact(c)), + ], + }) + this._mailboxes.innerHTML = '' + this._mailboxes.append(...Array.from(mailboxesElement)) + } + + private updateAllday = (e: DomEvent) => { + this._form.classList.toggle('open-calendar__event-edit--is-allday', (e.target as HTMLInputElement).checked) + } + + private addAttendee = (attendee: IcsAttendee) => { + const element = parseHtml(attendeeHtml, { + mailbox: this.getValueFromAttendee(attendee), + role: attendee.role || 'REQ-PARTICIPANT', + roles: attendeeRoleTypes.map(role => ({ key: role, translation: getTranslations().attendeeRoles[role] })), + participationStatus: attendee.partstat || 'NEEDS-ACTION', + participationStatuses: attendeePartStatusTypes.map(status => ({ + key: status, + translation: getTranslations().participationStatus[status], + })), + t: getTranslations().eventForm, + })[0] + this._attendees.appendChild(element) + + const remove = element.querySelector('button')! + const role = element.querySelector('select[name="attendee-role"]')! + const participationStatus = element.querySelector('select[name="participation-status"]')! + + remove.addEventListener('click', () => element.remove()) + role.value = attendee.role || 'REQ-PARTICIPANT' + participationStatus.value = attendee.partstat || 'NEEDS-ACTION' + } + + public onCreate = ({calendars, vCards, event, handleCreate, userContact}: EventEditCreateInfo) => { + this._form.classList.toggle('open-calendar__event-edit--create', true) + this._handleSave = handleCreate + this._handleDelete = null + this.open('', event, calendars, vCards, userContact) + } + public onSelect = ({ + calendarUrl, + calendars, + vCards, + event, + recurringEvent, + handleDelete, + handleUpdate, + userContact, + }: EventEditSelectInfo) => { + this._form.classList.toggle('open-calendar__event-edit--create', false) + this._handleSave = handleUpdate + this._handleDelete = handleDelete + if (!recurringEvent) this.open(calendarUrl, event, calendars, vCards, userContact) + else this._recurringPopup.open(editAll => { + return this.open( + calendarUrl, editAll ? recurringEvent : event, calendars, vCards, userContact) + }) + } + + public onMoveResize = ({ calendarUrl, event, start, end, handleUpdate }: EventEditMoveResizeInfo) => { + const newEvent = { ...event } + const startDelta = start.getTime() - event.start.date.getTime() + newEvent.start = offsetDate(newEvent.start, startDelta) + if (event.end) { + const endDelta = end.getTime() - event.end.date.getTime() + newEvent.end = offsetDate(event.end, endDelta) + } + handleUpdate( + { calendarUrl, event: newEvent } as CalendarEvent, + ) + } + + public onDelete = ({ calendarUrl, event, handleDelete}: EventEditDeleteInfo) => { + handleDelete({calendarUrl, event}) + } + + public open = ( + calendarUrl: string, + event: IcsEvent, + calendars: Calendar[], + vCards: AddressBookVCard[], + userContact?: Contact, + ) => { + this._userContact = userContact + this.setContacts( + vCards.filter(c => c.vCard.email !== null).map(c => c.vCard), + [...event.attendees ?? [], event.organizer].filter(a => a !== undefined), + ) + this.setCalendars(calendars) + + this._calendarUrl = calendarUrl + this._event = event + const localTzId = Intl.DateTimeFormat().resolvedOptions().timeZone + const localTzOffset = new Date().getTimezoneOffset() * TIME_MINUTE + const localStart = event.start.local ?? { + date: new Date(event.start.date.getTime() - localTzOffset), + timezone: localTzId, + } + const end = event.end ?? + offsetDate( + localStart, + getEventEndFromDuration(event.start.date, event.duration).getTime() - event.start.date.getTime(), + ) + const localEnd = end.local ?? { + date: new Date(end.date.getTime() - localTzOffset), + timezone: localTzId, + } + + const inputs = this._form.elements; + (inputs.namedItem('calendar') as HTMLInputElement).value = calendarUrl; + (inputs.namedItem('calendar') as HTMLInputElement).disabled = event.recurrenceId !== undefined; + // FIXME - CJ - 2025/06/03 - changing an object of calendar is not supported; + (inputs.namedItem('calendar') as HTMLInputElement).disabled ||= + !this._form.classList.contains('open-calendar__event-edit--create'); + (inputs.namedItem('summary') as HTMLInputElement).value = event.summary ?? ''; + (inputs.namedItem('location') as HTMLInputElement).value = event.location ?? ''; + (inputs.namedItem('allday') as HTMLInputElement).checked = isEventAllDay(event) + this._form.classList.toggle('open-calendar__event-edit--is-allday', isEventAllDay(event)) + const startDateTime = localStart.date.toISOString().split('T'); + (inputs.namedItem('start-date') as HTMLInputElement).value = startDateTime[0]; + (inputs.namedItem('start-time') as HTMLInputElement).value = startDateTime[1].slice(0, 5); + (inputs.namedItem('start-timezone') as HTMLInputElement).value = localStart.timezone + const endDateTime = localEnd.date.toISOString().split('T'); + (inputs.namedItem('end-date') as HTMLInputElement).value = endDateTime[0]; + (inputs.namedItem('end-time') as HTMLInputElement).value = endDateTime[1].slice(0, 5); + (inputs.namedItem('end-timezone') as HTMLInputElement).value = localEnd.timezone; + // TODO - CJ - 2025-07-03 - Add rich text support + (inputs.namedItem('description') as HTMLInputElement).value = event.description ?? ''; + + // TODO - CJ - 2025-07-03 - Check if needs to be hidden or done differently, + // as I believe Thunderbird also adds the organizer to the attendee list; + (inputs.namedItem('organizer-mailbox') as HTMLInputElement).value = event.organizer + ? this.getValueFromAttendee(event.organizer) + : '' + + const rrule = getRRuleString(event.recurrenceRule) + this._rruleUnchanged.value = rrule; + (inputs.namedItem('rrule') as HTMLInputElement).value = rrule; + (inputs.namedItem('rrule') as HTMLInputElement).disabled = event.recurrenceId !== undefined + + const userAttendeeInEvent = userContact !== undefined + ? event.attendees?.find(a => a.email === userContact.email) + : undefined + + if (userAttendeeInEvent !== undefined) { + this._form.classList.remove('open-calendar__event-edit--without-invite'); + (inputs.namedItem('user-participation-status') as HTMLSelectElement).value = + userAttendeeInEvent.partstat + ?? attendeeUserParticipationStatusTypes[0] + } else { + this._form.classList.add('open-calendar__event-edit--without-invite') + } + + + this._attendees.innerHTML = '' + for (const attendee of event.attendees ?? []) this.addAttendee(attendee) + + this._popup.setVisible(true) + } + + public save = async () => { + const data = new FormData(this._form) + const allDay = !!data.get('allday') + + const getTimeObject = (name: string): IcsDateObject => { + const date = data.get(`${name}-date`) as string + const time = data.get(`${name}-time`) as string + const timezone = data.get(`${name}-timezone`) as string + const offset = tzlib_get_offset(timezone, date, time) + return { + date: new Date(date + (allDay ? '' : `T${time}${offset}`)), + type: allDay ? 'DATE' : 'DATE-TIME', + local: timezone === 'UTC' ? undefined : { + date: new Date(date + (allDay ? '' : `T${time}Z`)), + timezone: tzlib_get_ical_block(timezone)[1].slice(5), + tzoffset: offset, + }, + } + } + + const mailboxes = data.getAll('attendee-mailbox') as string[] + const roles = data.getAll('attendee-role') as string[] + const participationStatuses = data.getAll('participation-status') as string[] + const rrule = data.get('rrule') as string + const description = data.get('description') as string + + const event: IcsEvent = { + ...this._event!, + summary: data.get('summary') as string, + location: data.get('location') as string || undefined, + start: getTimeObject('start'), + end: getTimeObject('end'), + description: description || undefined, + descriptionAltRep: description === this._event!.description ? this._event!.descriptionAltRep : undefined, + organizer: data.get('organizer-mailbox') + ? { + ...this._event!.organizer, + ...this.getContactFromValue(data.get('organizer-mailbox') as string), + } + : undefined, + attendees: mailboxes.map((mailbox, i) => { + const contact = this.getContactFromValue(mailbox) + return ({ + ...contact, + role: roles[i], + partstat: (contact.email === this._userContact?.email + ? data.get('user-participation-status') + : participationStatuses[i] + ) as IcsAttendeePartStatusType, + }) + }) || undefined, + recurrenceRule: rrule ? convertIcsRecurrenceRule(undefined, {value: rrule}) : undefined, + + // NOTE - CJ - 2025-07-03 - explicitly set `duration` to undefined as we set `end` + duration: undefined, + } + const response = await this._handleSave!({ calendarUrl: data.get('calendar') as string, event }) + if (response.ok) this._popup.setVisible(false) + } + + public cancel = () => { + this._popup.setVisible(false) + } + + public delete = async () => { + await this._handleDelete!({ calendarUrl: this._calendarUrl!, event: this._event!}) + this._popup.setVisible(false) + } + + public getContactFromValue = (value: string) => { + const contact = this._vCardContacts.find(c => this.getValueFromVCard(c) === value) + return contact + // NOTE - CJ - 2025-07-17 - we need to reconstruct an object as the spread syntax does not work for properties + ? { name: contact.name!, email: contact.email!} + : this._eventContacts.find(c => this.getValueFromContact(c) === value) + ?? mailboxToContact(value) + } + + public getValueFromAttendee = (attendee: IcsAttendee | IcsOrganizer): string => { + const vCard = this._vCardContacts.find(c => isSameContact(c, attendee)) + return vCard ? this.getValueFromVCard(vCard) : this.getValueFromContact(attendee) + } + + public getValueFromVCard = (contact: VCard) => (this._hideVCardEmails && contact.name) || contactToMailbox(contact) + public getValueFromContact = (contact: Contact) => contactToMailbox(contact) +} diff --git a/src/frontend/packages/open-calendar/src/eventeditpopup/recurringEventPopup.ts b/src/frontend/packages/open-calendar/src/eventeditpopup/recurringEventPopup.ts new file mode 100644 index 0000000..a780d37 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/eventeditpopup/recurringEventPopup.ts @@ -0,0 +1,49 @@ +import { Popup } from '../popup/popup' +import { parseHtml } from '../helpers/dom-helper' +import { getTranslations } from '../translations' + +const html = /*html*/` +
+ {{t.editRecurring}} +
+ + +
+
+` + +export class RecurringEventPopup { + + public _handleSelect?: (editAll: boolean) => void + + private _element: HTMLDivElement + private _popup: Popup + + public constructor(target: Node) { + this._popup = new Popup(target) + this._element = parseHtml(html, { t: getTranslations().recurringForm })[0] + this._popup.content.appendChild(this._element) + + const editAll = this._element.querySelector('.open-calendar__form__buttons [name="edit-all"]')! + const editSingle = this._element.querySelector( + '.open-calendar__form__buttons [name="edit-single"]', + )! + + editAll.addEventListener('click', () => this.close(true)) + editSingle.addEventListener('click', () => this.close(false)) + } + + public destroy = () => { + this._element.remove() + this._popup.destroy() + } + + public open = (handleSelect: (editAll: boolean) => void) => { + this._handleSelect = handleSelect + this._popup.setVisible(true) + } + private close = (editAll: boolean) => { + this._popup.setVisible(false) + this._handleSelect?.(editAll) + } +} diff --git a/src/frontend/packages/open-calendar/src/helpers/dav-helper.ts b/src/frontend/packages/open-calendar/src/helpers/dav-helper.ts new file mode 100644 index 0000000..ff50324 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/helpers/dav-helper.ts @@ -0,0 +1,273 @@ +import { tzlib_get_ical_block } from 'timezones-ical-library' +import { convertIcsCalendar, convertIcsTimezone, generateIcsCalendar, type IcsCalendar } from 'ts-ics' +import { createAccount, + fetchCalendars as davFetchCalendars, + fetchCalendarObjects as davFetchCalendarObjects, + createCalendarObject as davCreateCalendarObject, + updateCalendarObject as davUpdateCalendarObject, + deleteCalendarObject as davDeleteCalendarObject, + DAVNamespaceShort, + propfind, + type DAVCalendar, + type DAVCalendarObject, + type DAVAddressBook, + fetchAddressBooks as davFetchAddressBooks, + fetchVCards as davFetchVCards, +} from 'tsdav' +import { isServerSource } from './types-helper' +import type { Calendar, CalendarObject } from '../types/calendar' +import type { CalendarSource, ServerSource, CalendarResponse, AddressBookSource } from '../types/options' +import type { AddressBook, AddressBookObject } from '../types/addressbook' +import ICAL from 'ical.js' + +export function getEventObjectString(event: IcsCalendar) { + return generateIcsCalendar(event) +} + +export async function fetchCalendars(source: ServerSource | CalendarSource): Promise { + if (isServerSource(source)) { + const account = await createAccount({ + account: { serverUrl: source.serverUrl, accountType: 'caldav' }, + headers: source.headers, + fetchOptions: source.fetchOptions, + }) + const calendars = await davFetchCalendars({ account, headers: source.headers, fetchOptions: source.fetchOptions }) + return calendars.map(calendar => ({ ...calendar, headers: source.headers, fetchOptions: source.fetchOptions })) + } else { + const calendar = await davFetchCalendar({ + url: source.calendarUrl, + headers: source.headers, + fetchOptions: source.fetchOptions, + }) + return [{ ...calendar, headers: source.headers, fetchOptions: source.fetchOptions, uid: source.calendarUid }] + } +} + +export async function fetchCalendarObjects( + calendar: Calendar, + timeRange?: { start: string; end: string; }, + expand?: boolean, +): Promise<{ calendarObjects: CalendarObject[], recurringObjects: CalendarObject[] }> { + const davCalendarObjects = await davFetchCalendarObjects({ + calendar: calendar, + timeRange, expand, + headers: calendar.headers, + fetchOptions: calendar.fetchOptions, + }) + const calendarObjects = davCalendarObjects.map(o => ({ + url: o.url, + etag: o.etag, + data: convertIcsCalendar(undefined, o.data), + calendarUrl: calendar.url, + })) + const recurringObjectsUrls = new Set( + calendarObjects + .filter(c => c.data.events?.find(e => e.recurrenceId)) + .map(c => c.url), + ) + const davRecurringObjects = recurringObjectsUrls.size == 0 + ? [] + : await davFetchCalendarObjects({ + calendar: calendar, + objectUrls: Array.from(recurringObjectsUrls), + headers: calendar.headers, + fetchOptions: calendar.fetchOptions, + }) + const recurringObjects = davRecurringObjects.map(o => ({ + url: o.url, + etag: o.etag, + data: convertIcsCalendar(undefined, o.data), + calendarUrl: calendar.url, + })) + return { calendarObjects, recurringObjects } +} + +export async function createCalendarObject( + calendar: Calendar, + calendarObjectData: IcsCalendar, +): Promise { + validateTimezones(calendarObjectData) + for (const event of calendarObjectData.events ?? []) event.uid = crypto.randomUUID() + const uid = calendarObjectData.events?.[0].uid ?? crypto.randomUUID() + const iCalString = getEventObjectString(calendarObjectData) + const response = await davCreateCalendarObject({ + calendar, + iCalString, + filename: `${uid}.ics`, + headers: calendar.headers, + fetchOptions: calendar.fetchOptions, + }) + return { response, ical: iCalString } +} + +export async function updateCalendarObject( + calendar: Calendar, + calendarObject: CalendarObject, +): Promise { + validateTimezones(calendarObject.data) + const davCalendarObject: DAVCalendarObject = { + url: calendarObject.url, + etag: calendarObject.etag, + data: getEventObjectString(calendarObject.data), + } + const response = await davUpdateCalendarObject({ + calendarObject: davCalendarObject, + headers: calendar.headers, + fetchOptions: calendar.fetchOptions, + }) + return { response, ical: davCalendarObject.data } +} + +export async function deleteCalendarObject( + calendar: Calendar, + calendarObject: CalendarObject, +): Promise { + validateTimezones(calendarObject.data) + const davCalendarObject: DAVCalendarObject = { + url: calendarObject.url, + etag: calendarObject.etag, + data: getEventObjectString(calendarObject.data), + } + const response = await davDeleteCalendarObject({ + calendarObject: davCalendarObject, + headers: calendar.headers, + fetchOptions: calendar.fetchOptions, + }) + return { response, ical: davCalendarObject.data } + +} + +function validateTimezones(calendarObjectData: IcsCalendar) { + const calendar = calendarObjectData + const usedTimezones = calendar.events?.flatMap(e => [e.start.local?.timezone, e.end?.local?.timezone]) + const wantedTzIds = new Set(usedTimezones?.filter(s => s !== undefined)) + calendar.timezones ??= [] + + // Remove extra timezones + calendar.timezones = calendar.timezones.filter(tz => wantedTzIds.has(tz.id)) + + // Add missing timezones + wantedTzIds.forEach(tzid => { + if (calendar.timezones!.findIndex(t => t.id === tzid) === -1) { + calendar.timezones!.push(convertIcsTimezone(undefined, tzlib_get_ical_block(tzid)[0])) + } + }) +} + +// NOTE - CJ - 2025/07/03 - Inspired from https://github.com/natelindev/tsdav/blob/master/src/calendar.ts, fetchCalendars +async function davFetchCalendar(params: { + url: string, + headers?: Record, + fetchOptions?: RequestInit +}): Promise { + const { url, headers, fetchOptions } = params + const response = await propfind({ + url, + props: { + [`${DAVNamespaceShort.CALDAV}:calendar-description`]: {}, + [`${DAVNamespaceShort.CALDAV}:calendar-timezone`]: {}, + [`${DAVNamespaceShort.DAV}:displayname`]: {}, + [`${DAVNamespaceShort.CALDAV_APPLE}:calendar-color`]: {}, + [`${DAVNamespaceShort.CALENDAR_SERVER}:getctag`]: {}, + [`${DAVNamespaceShort.DAV}:resourcetype`]: {}, + [`${DAVNamespaceShort.CALDAV}:supported-calendar-component-set`]: {}, + [`${DAVNamespaceShort.DAV}:sync-token`]: {}, + }, + headers, + fetchOptions, + }) + const rs = response[0] + if (!rs.ok) { + throw new Error(`Calendar ${url} does not exists. ${rs.status} ${rs.statusText}`) + } + if (Object.keys(rs.props?.resourceType ?? {}).includes('calendar')) { + throw new Error(`${url} is not a ${rs.props?.resourceType} and not a calendar`) + } + const description = rs.props?.calendarDescription + const timezone = rs.props?.calendarTimezone + return { + description: typeof description === 'string' ? description : '', + timezone: typeof timezone === 'string' ? timezone : '', + url: params.url, + ctag: rs.props?.getctag, + calendarColor: rs.props?.calendarColor, + displayName: rs.props?.displayname._cdata ?? rs.props?.displayname, + components: Array.isArray(rs.props?.supportedCalendarComponentSet.comp) + // NOTE - CJ - 2025-07-03 - comp represents an list of XML nodes in the DAVResponse format + // sc could be `` + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ? rs.props?.supportedCalendarComponentSet.comp.map((sc: any) => sc._attributes.name) + : [rs.props?.supportedCalendarComponentSet.comp?._attributes.name], + resourcetype: Object.keys(rs.props?.resourcetype), + syncToken: rs.props?.syncToken, + } +} + +export async function fetchAddressBooks(source: ServerSource | AddressBookSource): Promise { + if (isServerSource(source)) { + const account = await createAccount({ + account: { serverUrl: source.serverUrl, accountType: 'caldav' }, + headers: source.headers, + fetchOptions: source.fetchOptions, + }) + const books = await davFetchAddressBooks({ account, headers: source.headers, fetchOptions: source.fetchOptions }) + return books.map(book => ({ ...book, headers: source.headers, fetchOptions: source.fetchOptions })) + } else { + const book = await davFetchAddressBook({ + url: source.addressBookUrl, + headers: source.headers, + fetchOptions: source.fetchOptions, + }) + return [{ ...book, headers: source.headers, fetchOptions: source.fetchOptions, uid: source.addressBookUid }] + } +} + + +// NOTE - CJ - 2025/07/03 - Inspired from https://github.com/natelindev/tsdav/blob/master/src/addressBook.ts#L73 +async function davFetchAddressBook(params: { + url: string, + headers?: Record, + fetchOptions?: RequestInit +}): Promise { + const { url, headers, fetchOptions } = params + const response = await propfind({ + url, + props: { + [`${DAVNamespaceShort.DAV}:displayname`]: {}, + [`${DAVNamespaceShort.CALENDAR_SERVER}:getctag`]: {}, + [`${DAVNamespaceShort.DAV}:resourcetype`]: {}, + [`${DAVNamespaceShort.DAV}:sync-token`]: {}, + }, + headers, + fetchOptions, + }) + const rs = response[0] + if (!rs.ok) { + throw new Error(`Address book ${url} does not exists. ${rs.status} ${rs.statusText}`) + } + if (Object.keys(rs.props?.resourceType ?? {}).includes('addressbook')) { + throw new Error(`${url} is not a ${rs.props?.resourceType} and not an addressbook`) + } + const displayName = rs.props?.displayname?._cdata ?? rs.props?.displayname + return { + url: url, + ctag: rs.props?.getctag, + displayName: typeof displayName === 'string' ? displayName : '', + resourcetype: Object.keys(rs.props?.resourcetype), + syncToken: rs.props?.syncToken, + } +} + +export async function fetchAddressBookObjects(addressBook: AddressBook): Promise { + const davVCards = await davFetchVCards({ + addressBook: addressBook, + headers: addressBook.headers, + fetchOptions: addressBook.fetchOptions, + }) + return davVCards.map(o => ({ + url: o.url, + etag: o.etag, + data: new ICAL.Component(ICAL.parse(o.data)), + addressBookUrl: addressBook.url, + })) +} diff --git a/src/frontend/packages/open-calendar/src/helpers/dom-helper.ts b/src/frontend/packages/open-calendar/src/helpers/dom-helper.ts new file mode 100644 index 0000000..82c8c6f --- /dev/null +++ b/src/frontend/packages/open-calendar/src/helpers/dom-helper.ts @@ -0,0 +1,11 @@ +import Mustache from 'mustache' + +export function parseHtml(html: string, format?: unknown): NodeListOf { + html = Mustache.render(html, format) + return Document.parseHTMLUnsafe(html).body.childNodes as NodeListOf +} + +export function escapeHtml(html: string): string { + // NOTE - CJ - 2025-07-07 - In Mustache, {{html}} escapes html whereas {{{html}}} and {{&html}} do not + return Mustache.render('{{html}}', { html }) +} diff --git a/src/frontend/packages/open-calendar/src/helpers/ics-helper.ts b/src/frontend/packages/open-calendar/src/helpers/ics-helper.ts new file mode 100644 index 0000000..c3f3930 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/helpers/ics-helper.ts @@ -0,0 +1,56 @@ +import { generateIcsRecurrenceRule, type IcsDateObject, type IcsEvent, type IcsRecurrenceRule } from 'ts-ics' +import { parseOneAddress } from 'email-addresses' +import type { EventUid } from '../types/calendar' +import type { Contact, VCard } from '../types/addressbook' + +export function isEventAllDay(event: IcsEvent) { + return event.start.type === 'DATE' || event.end?.type === 'DATE' +} + +export function offsetDate(date: IcsDateObject, offset: number): IcsDateObject { + return { + type: date.type, + date: new Date(date.date.getTime() + offset), + local: date.local && { + date: new Date(date.local.date.getTime() + offset), + timezone: date.local.timezone, + tzoffset: date.local.tzoffset, + }, + } +} + +export function isSameEvent(a: EventUid, b: EventUid) { + return a.uid === b.uid && a.recurrenceId?.value.date.getTime() === b.recurrenceId?.value.date.getTime() +} + +export function isRRuleSourceEvent(eventInstance: EventUid, event: EventUid) { + return eventInstance.uid === event.uid && event.recurrenceId === undefined +} + +export function getRRuleString(recurrenceRule?: IcsRecurrenceRule) { + if (!recurrenceRule) return '' + return generateIcsRecurrenceRule(recurrenceRule).trim().slice(6) +} + +// FIXME - CJ - 2025-07-11 - This function should only be used for display purposes +// It does not handle escape characters properly (quotes, comments) +// and parsing the result back to a contact with `mailboxToContact` may fail +// See https://datatracker.ietf.org/doc/html/rfc5322#section-3.4 the specs +export function contactToMailbox(contact: Contact | VCard): string { + return contact.name + ? `${contact.name} <${contact.email}>` + : contact.email! +} + +export function mailboxToContact(mailbox: string): Contact { + const parsed = parseOneAddress(mailbox) + if (parsed?.type !== 'mailbox') throw new Error(`Failed to parse mailbox '${mailbox}' `) + return { + name: parsed.name ?? undefined, + email: parsed.address, + } +} + +export function isSameContact(a: Contact | VCard, b: Contact | VCard) { + return a.name === b.name && a.email === b.email +} diff --git a/src/frontend/packages/open-calendar/src/helpers/types-helper.ts b/src/frontend/packages/open-calendar/src/helpers/types-helper.ts new file mode 100644 index 0000000..0b84d5f --- /dev/null +++ b/src/frontend/packages/open-calendar/src/helpers/types-helper.ts @@ -0,0 +1,22 @@ +import type { CalendarOptions, + SelectCalendarHandlers, + EventEditHandlers, + ServerSource, + VCardProvider, +} from '../types/options' + +export function isServerSource(source: ServerSource | unknown): source is ServerSource { + return (source as ServerSource).serverUrl !== undefined +} + +export function isVCardProvider(source: VCardProvider | unknown): source is VCardProvider { + return (source as VCardProvider).fetchContacts !== undefined +} + +export function hasEventHandlers(options: CalendarOptions): options is EventEditHandlers { + return (options as EventEditHandlers).onCreateEvent !== undefined +} + +export function hasCalendarHandlers(options: CalendarOptions): options is SelectCalendarHandlers { + return (options as SelectCalendarHandlers).onClickSelectCalendars !== undefined +} diff --git a/src/frontend/packages/open-calendar/src/index.css b/src/frontend/packages/open-calendar/src/index.css new file mode 100644 index 0000000..7df3d19 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/index.css @@ -0,0 +1,50 @@ +.open-calendar__form { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.open-calendar__form__content { + display: grid; + grid-template-columns: max-content max-content; + grid-gap: 5px; + align-items: baseline; +} + +.open-calendar__form__content label { + text-align: right; +} + +/* FIXME - CJ - 2025-07-03 - replace by something else that supports localization */ +.open-calendar__form__content label::after { + content: ":"; +} + +.open-calendar__form__content input[type=checkbox] { + justify-self: left; +} + +.open-calendar__form__list { + display: flex; + flex-direction: column; + grid-gap: 0.25rem; + margin-bottom: 0.25rem; +} + +.open-calendar__form__buttons { + display: flex; + gap: 1rem; +} + +.open-calendar__form__buttons>* { + flex-grow: 1; +} + +.open-calendar { + font-family: sans-serif; + height: 100%; +} + +.ec { + height: 100%; +} \ No newline at end of file diff --git a/src/frontend/packages/open-calendar/src/index.ts b/src/frontend/packages/open-calendar/src/index.ts new file mode 100644 index 0000000..e9e5f17 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/index.ts @@ -0,0 +1,23 @@ +import { CalendarElement } from './calendarelement/calendarElement' +import './index.css' +import { setTranslations, type ResourceBundle} from './translations' +import type { AddressBookSource, + CalendarOptions, + CalendarSource, + VCardProvider, + RecursivePartial, + ServerSource, +} from './types/options' + +export async function createCalendar( + calendarSources: (ServerSource | CalendarSource)[], + addressBookSources: (ServerSource | AddressBookSource | VCardProvider)[], + target: Element, + options?: CalendarOptions, + translations?: RecursivePartial, +) { + if (translations) setTranslations(translations) + const calendar = new CalendarElement() + await calendar.create(calendarSources, addressBookSources, target, options) + return calendar +} diff --git a/src/frontend/packages/open-calendar/src/popup/popup.css b/src/frontend/packages/open-calendar/src/popup/popup.css new file mode 100644 index 0000000..18bb686 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/popup/popup.css @@ -0,0 +1,24 @@ +.open-calendar__popup__overlay { + position: fixed; + width: 100vw; + height: 100vh; + left: 0px; + top: 0px; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 2000; +} + +.open-calendar__popup--hidden { + display: none; +} + +.open-calendar__popup__frame { + width: fit-content; + height: fit-content; + background-color: white; + padding: 0.5rem; + border-radius: 10px; +} \ No newline at end of file diff --git a/src/frontend/packages/open-calendar/src/popup/popup.ts b/src/frontend/packages/open-calendar/src/popup/popup.ts new file mode 100644 index 0000000..1d6a48b --- /dev/null +++ b/src/frontend/packages/open-calendar/src/popup/popup.ts @@ -0,0 +1,35 @@ +import './popup.css' +import { parseHtml } from '../helpers/dom-helper' + +const html = /*html*/` +
+
+
` + +export class Popup { + + private _node: HTMLDivElement + public content: HTMLDivElement + + constructor(target: Node) { + this._node = parseHtml(html)[0] + target.appendChild(this._node) + + this.content = this._node.firstElementChild as HTMLDivElement + + window.addEventListener('mousedown', e => { + if (this._node.classList.contains('open-calendar__popup--hidden')) return + if (e.target instanceof Element && (e.target === this.content || e.target.contains(this.content))) { + this.setVisible(false) + } + }) + } + + public destroy = () => { + this._node.remove() + } + + setVisible = (visible: boolean) => { + this._node.classList.toggle('open-calendar__popup--hidden', !visible) + } +} diff --git a/src/frontend/packages/open-calendar/src/translations.ts b/src/frontend/packages/open-calendar/src/translations.ts new file mode 100644 index 0000000..243774f --- /dev/null +++ b/src/frontend/packages/open-calendar/src/translations.ts @@ -0,0 +1,123 @@ +import type { RecursivePartial } from './types/options' + +// HACK - CJ - 2025-07-03 - Ideally, this object would have been a json file and imported with: +// `import en from 'locale/en/translation.json'` +// However, the lib used to create the declarations file `index.d.ts` thinks this is ts import +// and looks for the file `locale/en/translation.json.d.ts` which doesn't exists. +const en = { + 'calendarElement': { + 'timeGridDay': 'Day', + 'timeGridWeek': 'Week', + 'dayGridMonth': 'Month', + 'listDay': 'List', + 'listWeek': 'List Week', + 'listMonth': 'List Month', + 'listYear': 'List Year', + 'today': 'Today', + 'allDay': 'Daily', + 'calendars': 'Calendars', + 'newEvent': 'New Event', + }, + 'eventForm': { + 'allDay': 'Daily', + 'calendar': 'Calendar', + 'title': 'Title', + 'location': 'Location', + 'start': 'Start', + 'end': 'End', + 'organizer': 'Organizer', + 'attendees': 'Attendees', + 'addAttendee': 'Add attendee', + 'description': 'Description', + 'delete': 'Delete', + 'cancel': 'Cancel', + 'save': 'Save', + 'chooseACalendar': '-- Choose a calendar --', + 'rrule': 'Frequency', + 'userInvite': 'You were invited to this event', + }, + 'eventBody': { + 'organizer': 'Organizer', + 'participation_require': 'Required participant', + 'participation_optional': 'Optional participant', + 'non_participant': 'Non participant', + 'participation_confirmed': 'Participation confirmed', + 'participation_pending': 'Participation pending', + 'participation_confirmed_tentative': 'Participation confirmed tentative', + 'participation_declined': 'Participation declined', + }, + 'recurringForm': { + 'editRecurring': 'This is a recurring event', + 'editAll': 'Edit all occurrences', + 'editSingle': 'Edit this occurrence only', + }, + 'participationStatus': { + 'NEEDS-ACTION': 'Needs to answer', + 'ACCEPTED': 'Accepted', + 'DECLINED': 'Declined', + 'TENTATIVE': 'Tentatively accepted', + 'DELEGATED': 'Delegated', + }, + 'userParticipationStatus': { + 'NEEDS-ACTION': 'Not answered', + 'ACCEPTED': 'Accept', + 'DECLINED': 'Decline', + 'TENTATIVE': 'Accept tentatively', + }, + 'attendeeRoles': { + 'CHAIR': 'Chair', + 'REQ-PARTICIPANT': 'Required participant', + 'OPT-PARTICIPANT': 'Optional participant', + 'NON-PARTICIPANT': 'Non participant', + }, + 'rrules': { + 'none': 'Never', + 'unchanged': 'Keep existing', + 'FREQ=DAILY': 'Daily', + 'FREQ=WEEKLY': 'Weekly', + 'BYDAY=MO,TU,WE,TH,FR;FREQ=DAILY': 'Workdays', + 'INTERVAL=2;FREQ=WEEKLY': 'Every two week', + 'FREQ=MONTHLY': 'Monthly', + 'FREQ=YEARLY': 'Yearly', + }, +} + +export type ResourceBundle = typeof en + +let translations = en + +export const setTranslations = (bundle: RecursivePartial) => translations = { + calendarElement: { + ...en.calendarElement, + ...bundle.calendarElement, + }, + eventForm: { + ...en.eventForm, + ...bundle.eventForm, + }, + eventBody: { + ...en.eventBody, + ...bundle.eventBody, + }, + recurringForm: { + ...en.recurringForm, + ...bundle.recurringForm, + }, + userParticipationStatus: { + ...en.userParticipationStatus, + ...bundle.userParticipationStatus, + }, + participationStatus: { + ...en.participationStatus, + ...bundle.participationStatus, + }, + attendeeRoles: { + ...en.attendeeRoles, + ...bundle.attendeeRoles, + }, + rrules: { + ...en.rrules, + ...bundle.rrules, + }, +} +export const getTranslations = () => translations diff --git a/src/frontend/packages/open-calendar/src/types/addressbook.ts b/src/frontend/packages/open-calendar/src/types/addressbook.ts new file mode 100644 index 0000000..d98f79c --- /dev/null +++ b/src/frontend/packages/open-calendar/src/types/addressbook.ts @@ -0,0 +1,30 @@ +import type { DAVAddressBook } from 'tsdav' +import ICAL from 'ical.js' + +export type AddressBook = DAVAddressBook & { + headers?: Record + uid?: unknown +} + +export type AddressBookObject = { + data: ICAL.Component + etag?: string + url: string + addressBookUrl: string +} + +export type VCard = { + name: string + email: string | null +} + +export type AddressBookVCard = { + // INFO - 2025-07-24 - addressBookUrl is undefined when the contact is from a VCardProvider + addressBookUrl?: string + vCard: VCard +} + +export type Contact = { + name?: string + email: string +} diff --git a/src/frontend/packages/open-calendar/src/types/calendar.ts b/src/frontend/packages/open-calendar/src/types/calendar.ts new file mode 100644 index 0000000..dfecdb9 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/types/calendar.ts @@ -0,0 +1,39 @@ +import type { IcsCalendar, IcsEvent, IcsRecurrenceId } from 'ts-ics' +import type { DAVCalendar } from 'tsdav' + +// TODO - CJ - 2025-07-03 - add generic +// TODO - CJ - 2025-07-03 - add options to support IcsEvent custom props +export type Calendar = DAVCalendar & { + // INFO - CJ - 2025-07-03 - Useful fields from 'DAVCalendar' + // ctag?: string + // description?: string; + // displayName?: string | Record; + // calendarColor?: string + // url: string + // fetchOptions?: RequestInit + headers?: Record + uid?: unknown +} + +export type CalendarObject = { + data: IcsCalendar + etag?: string + url: string + calendarUrl: string +} + +export type CalendarEvent = { + calendarUrl: string + event: IcsEvent +} + +export type EventUid = { + uid: string + recurrenceId?: IcsRecurrenceId +} + +export type DisplayedCalendarEvent = { + calendarUrl: string + event: IcsEvent + recurringEvent?: IcsEvent +} diff --git a/src/frontend/packages/open-calendar/src/types/options.ts b/src/frontend/packages/open-calendar/src/types/options.ts new file mode 100644 index 0000000..b12c0e9 --- /dev/null +++ b/src/frontend/packages/open-calendar/src/types/options.ts @@ -0,0 +1,160 @@ +import type { IcsEvent } from 'ts-ics' +import type { Calendar, CalendarEvent } from './calendar' +import type { AddressBookVCard, Contact, VCard } from './addressbook' +import type { attendeeRoleTypes, availableViews } from '../contants' + +export type RecursivePartial = { + [P in keyof T]?: RecursivePartial +} + +export type DomEvent = GlobalEventHandlersEventMap[keyof GlobalEventHandlersEventMap] + +export type ServerSource = { + serverUrl: string + headers?: Record + fetchOptions?: RequestInit +} + +export type CalendarSource = { + calendarUrl: string + calendarUid?: unknown + headers?: Record + fetchOptions?: RequestInit +} + +export type AddressBookSource = { + addressBookUrl: string + addressBookUid?: unknown + headers?: Record + fetchOptions?: RequestInit +} + +export type VCardProvider = { + fetchContacts: () => Promise +} + +export type View = typeof availableViews[number] +export type IcsAttendeeRoleType = typeof attendeeRoleTypes[number] + + +export type SelectedCalendar = { + url: string + selected: boolean +} + +export type SelectCalendarCallback = (calendar: SelectedCalendar) => void +export type SelectCalendarsClickInfo = { + jsEvent: DomEvent + calendars: Calendar[] + selectedCalendars: Set + handleSelect: SelectCalendarCallback +} +export type SelectCalendarHandlers = { + onClickSelectCalendars: (info: SelectCalendarsClickInfo) => void, +} + + +export type EventBodyInfo = { + calendar: Calendar + vCards: AddressBookVCard[] + event: IcsEvent + view: View + userContact?: Contact +} +export type BodyHandlers = { + getEventBody: (info: EventBodyInfo) => Node[] +} + +export type EventEditCallback = (event: CalendarEvent) => Promise +export type EventEditCreateInfo = { + jsEvent: DomEvent + userContact?: Contact, + event: IcsEvent + calendars: Calendar[] + vCards: AddressBookVCard[] + handleCreate: EventEditCallback +} +export type EventEditSelectInfo = { + jsEvent: DomEvent + userContact?: Contact, + calendarUrl: string + event: IcsEvent + recurringEvent?: IcsEvent + calendars: Calendar[] + vCards: AddressBookVCard[] + handleUpdate: EventEditCallback + handleDelete: EventEditCallback +} +export type EventEditMoveResizeInfo = { + jsEvent: DomEvent + calendarUrl: string + userContact?: Contact, + event: IcsEvent + recurringEvent?: IcsEvent, + start: Date, + end: Date, + handleUpdate: EventEditCallback +} +export type EventEditDeleteInfo = { + jsEvent: DomEvent + userContact?: Contact, + calendarUrl: string + event: IcsEvent + recurringEvent?: IcsEvent + handleDelete: EventEditCallback +} +export type EventEditHandlers = { + onCreateEvent: (info: EventEditCreateInfo) => void, + onSelectEvent: (info: EventEditSelectInfo) => void, + onMoveResizeEvent: (info: EventEditMoveResizeInfo) => void, + onDeleteEvent: (info: EventEditDeleteInfo) => void, +} + +export type EventChangeInfo = { + calendarUrl: string + event: IcsEvent + ical: string +} + +export type EventChangeHandlers = { + onEventCreated?: (info: EventChangeInfo) => void + onEventUpdated?: (info: EventChangeInfo) => void + onEventDeleted?: (info: EventChangeInfo) => void +} + +export type CalendarElementOptions = { + view?: View + views?: View[] + locale?: string + date?: Date + editable?: boolean +} + +export type CalendarClientOptions = { + userContact?: Contact +} + +export type DefaultComponentsOptions = { + hideVCardEmails?: boolean +} + +export type CalendarOptions = + // NOTE - CJ - 2025-07-03 + // May define individual options or not + CalendarElementOptions + // May define individual options or not + & CalendarClientOptions + // Must define all handlers or none + & (SelectCalendarHandlers | Record) + // Must define all handlers or none + & (EventEditHandlers | Record) + // May define individual handlers or not + & EventChangeHandlers + // May define handlers or not, but they will be assigned a default value if they are not + & Partial + & DefaultComponentsOptions + +export type CalendarResponse = { + response: Response + ical: string +} diff --git a/src/frontend/packages/open-calendar/src/vite-env.d.ts b/src/frontend/packages/open-calendar/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/frontend/packages/open-calendar/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/frontend/packages/open-calendar/tsconfig.json b/src/frontend/packages/open-calendar/tsconfig.json new file mode 100644 index 0000000..781d7f4 --- /dev/null +++ b/src/frontend/packages/open-calendar/tsconfig.json @@ -0,0 +1,36 @@ +{ + "include": ["src/**/*"], + "exclude": ["node_modules", "vite.config.ts"], + "compilerOptions": { + "outDir": "./dist/", + "module": "esnext", + "target": "es2020", + "lib": ["ES2020", "DOM"], + "useDefineForClassFields": true, + "skipLibCheck": true, + "types": [], + "declaration": true, + "declarationDir": "./build/", + "esModuleInterop": true, + /* Bundler mode */ + "moduleResolution": "node", + "resolveJsonModule": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitAny": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "allowSyntheticDefaultImports": true, + /* FIXME - CJ - 2025-07-03 - Compilation worked file when I added `tsconfig-paths-webpack-plugin` but I could not find a working plugin for the .d.ts files */ + // "baseUrl": "./src", + // "paths": { + // "@helpers/*": ["./helpers/*"], + // "@calendar-types": ["./types.ts"] + // }, + }, +} \ No newline at end of file diff --git a/src/frontend/packages/open-calendar/vite.config.ts b/src/frontend/packages/open-calendar/vite.config.ts new file mode 100644 index 0000000..7826993 --- /dev/null +++ b/src/frontend/packages/open-calendar/vite.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from 'vite' +import { nodePolyfills } from 'vite-plugin-node-polyfills' +// INFO - CJ - 2025-07-03 - This plugin show tsc errors on vite dev +import pluginChecker from 'vite-plugin-checker' + +export default defineConfig({ + plugins: [ + nodePolyfills(), + pluginChecker({ typescript: true }), + ], + build: { + lib: { + entry: './src/index.ts', + name: 'CalendarClient', + fileName: 'index', + }, + }, + resolve: { + alias: { + 'node-fetch': 'axios', + }, + }, +}) diff --git a/src/frontend/packages/open-calendar/webpack.config.js b/src/frontend/packages/open-calendar/webpack.config.js new file mode 100644 index 0000000..ec63624 --- /dev/null +++ b/src/frontend/packages/open-calendar/webpack.config.js @@ -0,0 +1,43 @@ +const path = require('path') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') +const DtsBundleWebpack = require('dts-bundle-webpack') +const isProduction = process.env.NODE_ENV === 'production' || true +const name = 'open-dav-calendar' + +module.exports = { + mode: isProduction ? 'production' : 'development', + entry: { + index: "./src/index.ts", + }, + target: 'web', + plugins: [ + new NodePolyfillPlugin(), + new DtsBundleWebpack({ + name: name, + main: path.resolve(__dirname, "build/index.d.ts"), + out: path.resolve(__dirname, "dist/index.d.ts"), + }) + ], + module: { + rules: [{ + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/, + }, { + test: /\.css$/, + use: ['style-loader', 'css-loader'] + }], + }, + resolve: { + extensions: ['.ts', '.js'], + }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].js', + library: { + type: 'umd', + name: name, + umdNamedDefine: true + } + } +} diff --git a/src/frontend/packages/open-calendar/yarn.lock b/src/frontend/packages/open-calendar/yarn.lock new file mode 100644 index 0000000..0393425 --- /dev/null +++ b/src/frontend/packages/open-calendar/yarn.lock @@ -0,0 +1,3636 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== + +"@discoveryjs/json-ext@^0.6.1": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz#f13c7c205915eb91ae54c557f5e92bddd8be0e83" + integrity sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ== + +"@esbuild/aix-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" + integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== + +"@esbuild/android-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" + integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== + +"@esbuild/android-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" + integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== + +"@esbuild/android-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" + integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== + +"@esbuild/darwin-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" + integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== + +"@esbuild/darwin-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" + integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== + +"@esbuild/freebsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" + integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== + +"@esbuild/freebsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" + integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== + +"@esbuild/linux-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" + integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== + +"@esbuild/linux-arm@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" + integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== + +"@esbuild/linux-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" + integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== + +"@esbuild/linux-loong64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" + integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== + +"@esbuild/linux-mips64el@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" + integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== + +"@esbuild/linux-ppc64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" + integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== + +"@esbuild/linux-riscv64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" + integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== + +"@esbuild/linux-s390x@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" + integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== + +"@esbuild/linux-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" + integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== + +"@esbuild/netbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" + integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== + +"@esbuild/netbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" + integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== + +"@esbuild/openbsd-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" + integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== + +"@esbuild/openbsd-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" + integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== + +"@esbuild/sunos-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" + integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== + +"@esbuild/win32-arm64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" + integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== + +"@esbuild/win32-ia32@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" + integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== + +"@esbuild/win32-x64@0.25.5": + version "0.25.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" + integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz#607084630c6c033992a082de6e6fbc1a8b52175a" + integrity sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/config-array@^0.21.0": + version "0.21.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.0.tgz#abdbcbd16b124c638081766392a4d6b509f72636" + integrity sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.3.0.tgz#3e09a90dfb87e0005c7694791e58e97077271286" + integrity sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw== + +"@eslint/core@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" + integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" + integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.14.0.tgz#326289380968eaf7e96f364e1e4cf8f3adf2d003" + integrity sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.15.1": + version "0.15.1" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.15.1.tgz#d530d44209cbfe2f82ef86d6ba08760196dd3b60" + integrity sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/css-tree@^3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@eslint/css-tree/-/css-tree-3.6.1.tgz#7e162e2884b4581bb74e8cfe9ff1eb42cf87fc9f" + integrity sha512-5DIsBME23tUQD5zHD+T38lC2DG4jB8x8JRa+yDncLne2TIZA0VuCpcSazOX1EC+sM/q8w24qeevXfmfsIxAeqA== + dependencies: + mdn-data "2.21.0" + source-map-js "^1.0.1" + +"@eslint/css@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@eslint/css/-/css-0.9.0.tgz#fc095bb0a0ec5da5c7482d6360a64ba93743575b" + integrity sha512-fq8hYnjipdzVDSU/bXqv7qlvdjDA27Nq7DhQXzlPElLlVon3lnKovIM/6HaUrq1bz7EPgRobr+vOhpeM6z0X4w== + dependencies: + "@eslint/core" "^0.14.0" + "@eslint/css-tree" "^3.6.1" + "@eslint/plugin-kit" "^0.3.1" + +"@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + 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" + +"@eslint/js@9.30.0", "@eslint/js@^9.29.0": + version "9.30.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.30.0.tgz#c396fa450d5505dd9b7b8846b33f0491aebd9a2d" + integrity sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww== + +"@eslint/json@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eslint/json/-/json-0.12.0.tgz#7d1cb7152d01f3837703c154a5b38233f409395e" + integrity sha512-n/7dz8HFStpEe4o5eYk0tdkBdGUS/ZGb0GQCeDWN1ZmRq67HMHK4vC33b0rQlTT6xdZoX935P4vstiWVk5Ying== + dependencies: + "@eslint/core" "^0.12.0" + "@eslint/plugin-kit" "^0.2.7" + "@humanwhocodes/momoa" "^3.3.4" + natural-compare "^1.4.0" + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.2.7": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" + integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== + dependencies: + "@eslint/core" "^0.13.0" + levn "^0.4.1" + +"@eslint/plugin-kit@^0.3.1": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.3.3.tgz#32926b59bd407d58d817941e48b2a7049359b1fd" + integrity sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag== + dependencies: + "@eslint/core" "^0.15.1" + levn "^0.4.1" + +"@event-calendar/core@^4.4.0": + version "4.5.0" + resolved "https://registry.yarnpkg.com/@event-calendar/core/-/core-4.5.0.tgz#bdd770f9e118d0d44b25e503471e581b604470f9" + integrity sha512-H7z3MCmXJP7Gdzdf9cxA3rR9ANw15y8cD041twStNQ3S7PniqcH+qygvZOHp45vTxNj2HA9vOUR4Reno8AK89Q== + dependencies: + svelte "^5.34.8" + +"@fortawesome/fontawesome-common-types@6.7.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz#7123d74b0c1e726794aed1184795dbce12186470" + integrity sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg== + +"@fortawesome/fontawesome-svg-core@^6.7.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz#0ac6013724d5cc327c1eb81335b91300a4fce2f2" + integrity sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA== + dependencies: + "@fortawesome/fontawesome-common-types" "6.7.2" + +"@fortawesome/free-regular-svg-icons@^6.7.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz#f1651e55e6651a15589b0569516208f9c65f96db" + integrity sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g== + dependencies: + "@fortawesome/fontawesome-common-types" "6.7.2" + +"@fortawesome/free-solid-svg-icons@^6.7.2": + version "6.7.2" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz#fe25883b5eb8464a82918599950d283c465b57f6" + integrity sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA== + dependencies: + "@fortawesome/fontawesome-common-types" "6.7.2" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/momoa@^3.3.4": + version "3.3.8" + resolved "https://registry.yarnpkg.com/@humanwhocodes/momoa/-/momoa-3.3.8.tgz#b00630bf689b6f758419c029e15a4be25c12179b" + integrity sha512-/3PZzor2imi/RLLcnHztkwA79txiVvW145Ve2cp5dxRcH5qOUNJPToasqLFHniTfw4B4lT7jGDdBOPXbXYlIMQ== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + +"@isaacs/balanced-match@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29" + integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ== + +"@isaacs/brace-expansion@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz#4b3dabab7d8e75a429414a96bd67bf4c1d13e0f3" + integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA== + dependencies: + "@isaacs/balanced-match" "^4.0.1" + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.10" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.10.tgz#1cad974c8478e644c5cbce2a4b738137bb64bd4f" + integrity sha512-HM2F4B9N4cA0RH2KQiIZOHAZqtP4xGS4IZ+SFe1SIbO4dyjf9MTY2Bo3vHYnm0hglWfXqBrzUBSa+cJfl3Xvrg== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.8.tgz#0af4be466bcbcbc7206f69623e32b3cefe3b39cd" + integrity sha512-3EDAPd0B8X1gsQQgGHU8vyxSp2MB414z3roN67fY7nI0GV3GDthHfaWcbCfrC95tpAzA5xUvAuoO9Dxx/ywwRQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.2.tgz#4f25c8f17f28ccf70ed16e03f8fbf6d3998cb8fd" + integrity sha512-gKYheCylLIedI+CSZoDtGkFV9YEBxRRVcfCH7OfAqh4TyUyRjEE6WVE/aXDXX0p8BIe/QgLcaAoI0220KRRFgg== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.27" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.27.tgz#3139cfeafce3aa9918454cce8b219eee39fd7df2" + integrity sha512-VO95AxtSFMelbg3ouljAYnfvTEwSWVt/2YLf+U5Ejd8iT5mXE2Sa/1LGyvySMne2CGsepGLI7KpF3EzE3Aq9Mg== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@rollup/plugin-inject@^5.0.5": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz#616f3a73fe075765f91c5bec90176608bed277a3" + integrity sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg== + dependencies: + "@rollup/pluginutils" "^5.0.1" + estree-walker "^2.0.2" + magic-string "^0.30.3" + +"@rollup/pluginutils@^5.0.1": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.2.0.tgz#eac25ca5b0bdda4ba735ddaca5fbf26bd435f602" + integrity sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + +"@rollup/rollup-android-arm-eabi@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz#f768e3b2b0e6b55c595d7a053652c06413713983" + integrity sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w== + +"@rollup/rollup-android-arm64@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz#40379fd5501cfdfd7d8f86dfa1d3ce8d3a609493" + integrity sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ== + +"@rollup/rollup-darwin-arm64@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz#972c227bc89fe8a38a3f0c493e1966900e4e1ff7" + integrity sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg== + +"@rollup/rollup-darwin-x64@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz#96c919dcb87a5aa7dec5f7f77d90de881e578fdd" + integrity sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw== + +"@rollup/rollup-freebsd-arm64@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz#d199d8eaef830179c0c95b7a6e5455e893d1102c" + integrity sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA== + +"@rollup/rollup-freebsd-x64@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz#cab01f9e06ca756c1fabe87d64825ae016af4713" + integrity sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw== + +"@rollup/rollup-linux-arm-gnueabihf@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz#f6f1c42036dba0e58dc2315305429beff0d02c78" + integrity sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ== + +"@rollup/rollup-linux-arm-musleabihf@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz#1157e98e740facf858993fb51431dce3a4a96239" + integrity sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw== + +"@rollup/rollup-linux-arm64-gnu@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz#b39db73f8a4c22e7db31a4f3fd45170105f33265" + integrity sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ== + +"@rollup/rollup-linux-arm64-musl@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz#4043398049fe4449c1485312d1ae9ad8af4056dd" + integrity sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g== + +"@rollup/rollup-linux-loongarch64-gnu@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz#855a80e7e86490da15a85dcce247dbc25265bc08" + integrity sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew== + +"@rollup/rollup-linux-powerpc64le-gnu@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz#8cf843cb7ab1d42e1dda680937cf0a2db6d59047" + integrity sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA== + +"@rollup/rollup-linux-riscv64-gnu@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz#287c085472976c8711f16700326f736a527f2f38" + integrity sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw== + +"@rollup/rollup-linux-riscv64-musl@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz#095ad5e53a54ba475979f1b3226b92440c95c892" + integrity sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg== + +"@rollup/rollup-linux-s390x-gnu@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz#a3dec8281d8f2aef1703e48ebc65d29fe847933c" + integrity sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw== + +"@rollup/rollup-linux-x64-gnu@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz#4b211e6fd57edd6a134740f4f8e8ea61972ff2c5" + integrity sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw== + +"@rollup/rollup-linux-x64-musl@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz#3ecbf8e21b4157e57bb15dc6837b6db851f9a336" + integrity sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g== + +"@rollup/rollup-win32-arm64-msvc@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz#d4aae38465b2ad200557b53c8c817266a3ddbfd0" + integrity sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg== + +"@rollup/rollup-win32-ia32-msvc@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz#0258e8ca052abd48b23fd6113360fa0cd1ec3e23" + integrity sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A== + +"@rollup/rollup-win32-x64-msvc@4.44.1": + version "4.44.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz#1c982f6a5044ffc2a35cd754a0951bdcb44d5ba0" + integrity sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug== + +"@standard-schema/spec@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" + integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== + +"@stylistic/eslint-plugin@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-5.1.0.tgz#98769a3e6fc68d92deba20538341b0ea7923b3ce" + integrity sha512-TJRJul4u/lmry5N/kyCU+7RWWOk0wyXN+BncRlDYBqpLFnzXkd7QGVfN7KewarFIXv0IX0jSF/Ksu7aHWEDeuw== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/types" "^8.34.1" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + estraverse "^5.3.0" + picomatch "^4.0.2" + +"@sveltejs/acorn-typescript@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz#f518101d1b2e12ce80854f1cd850d3b9fb91d710" + integrity sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ== + +"@types/detect-indent@0.1.30": + version "0.1.30" + resolved "https://registry.yarnpkg.com/@types/detect-indent/-/detect-indent-0.1.30.tgz#dc682bb412b4e65ba098e70edad73b4833fb910d" + integrity sha512-AUmj9JHuHTD94slY1WR1VulFxRGC6D1pcNCN0MCulKFyiihvV/28lLS8oRHgfmc2Cxq954J8Vmosa8qzm7PLGQ== + +"@types/eslint-scope@^3.7.7": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.5", "@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/event-calendar__core@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@types/event-calendar__core/-/event-calendar__core-4.4.0.tgz#9a7ae0c7bceb0bcb0c859e9eafe6a16377583b7c" + integrity sha512-8Y4k+acsniRXn1bR0UGgDJE0Qquuk4+Dgx43VS1isIcAK00sfdu2hs726ikuWWzLZGm44ZfYtbq1eM84RtfT4g== + dependencies: + svelte "^5" + +"@types/glob@5.0.30": + version "5.0.30" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.30.tgz#1026409c5625a8689074602808d082b2867b8a51" + integrity sha512-ZM05wDByI+WA153sfirJyEHoYYoIuZ7lA2dB/Gl8ymmpMTR78fNRtDMqa7Z6SdH4fZdLWZNRE6mZpx3XqBOrHw== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/minimatch@*": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + +"@types/mkdirp@0.3.29": + version "0.3.29" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.3.29.tgz#7f2ad7ec55f914482fc9b1ec4bb1ae6028d46066" + integrity sha512-QRLQpFsIQGO2k8pupga9abfei85GKotAtQ+F6xuQmSGomUt6C52TyMiTFpP8kUwuPKr00gNtu3itLlC6gvI/NA== + +"@types/mustache@^4.2.6": + version "4.2.6" + resolved "https://registry.yarnpkg.com/@types/mustache/-/mustache-4.2.6.tgz#9d4f903f4ad373699b253aa1369727bc5042811f" + integrity sha512-t+8/QWTAhOFlrF1IVZqKnMRJi84EgkIK5Kh0p2JV4OLywUvCwJPFxbJAl7XAow7DVIHsF+xW9f1MVzg0L6Szjw== + +"@types/node@*", "@types/node@^24.0.3": + version "24.0.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.7.tgz#ee580f7850c7eabaeef61ef96b8d8c04fdf94f53" + integrity sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw== + dependencies: + undici-types "~7.8.0" + +"@types/node@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.0.tgz#acaa89247afddc7967e9902fd11761dadea1a555" + integrity sha512-j2tekvJCO7j22cs+LO6i0kRPhmQ9MXaPZ55TzOc1lzkN5b6BWqq4AFjl04s1oRRQ1v5rSe+KEvnLUSTonuls/A== + +"@typescript-eslint/eslint-plugin@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.35.0.tgz#515170100ff867445fe0a17ce05c14fc5fd9ca63" + integrity sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.35.0" + "@typescript-eslint/type-utils" "8.35.0" + "@typescript-eslint/utils" "8.35.0" + "@typescript-eslint/visitor-keys" "8.35.0" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/parser@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.35.0.tgz#20a0e17778a329a6072722f5ac418d4376b767d2" + integrity sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA== + dependencies: + "@typescript-eslint/scope-manager" "8.35.0" + "@typescript-eslint/types" "8.35.0" + "@typescript-eslint/typescript-estree" "8.35.0" + "@typescript-eslint/visitor-keys" "8.35.0" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.35.0.tgz#00bd77e6845fbdb5684c6ab2d8a400a58dcfb07b" + integrity sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.35.0" + "@typescript-eslint/types" "^8.35.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.35.0.tgz#8ccb2ab63383544fab98fc4b542d8d141259ff4f" + integrity sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA== + dependencies: + "@typescript-eslint/types" "8.35.0" + "@typescript-eslint/visitor-keys" "8.35.0" + +"@typescript-eslint/tsconfig-utils@8.35.0", "@typescript-eslint/tsconfig-utils@^8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.35.0.tgz#6e05aeb999999e31d562ceb4fe144f3cbfbd670e" + integrity sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA== + +"@typescript-eslint/type-utils@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.35.0.tgz#0201eae9d83ffcc3451ef8c94f53ecfbf2319ecc" + integrity sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA== + dependencies: + "@typescript-eslint/typescript-estree" "8.35.0" + "@typescript-eslint/utils" "8.35.0" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/types@8.35.0", "@typescript-eslint/types@^8.34.1", "@typescript-eslint/types@^8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.35.0.tgz#e60d062907930e30008d796de5c4170f02618a93" + integrity sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ== + +"@typescript-eslint/typescript-estree@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.35.0.tgz#86141e6c55b75bc1eaecc0781bd39704de14e52a" + integrity sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w== + dependencies: + "@typescript-eslint/project-service" "8.35.0" + "@typescript-eslint/tsconfig-utils" "8.35.0" + "@typescript-eslint/types" "8.35.0" + "@typescript-eslint/visitor-keys" "8.35.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 "^2.1.0" + +"@typescript-eslint/utils@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.35.0.tgz#aaf0afab5ab51ea2f1897002907eacd9834606d5" + integrity sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.35.0" + "@typescript-eslint/types" "8.35.0" + "@typescript-eslint/typescript-estree" "8.35.0" + +"@typescript-eslint/visitor-keys@8.35.0": + version "8.35.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.35.0.tgz#93e905e7f1e94d26a79771d1b1eb0024cb159dbf" + integrity sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g== + dependencies: + "@typescript-eslint/types" "8.35.0" + eslint-visitor-keys "^4.2.1" + +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== + dependencies: + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== + +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== + +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== + +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== + +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" + +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== + +"@webassemblyjs/wasm-edit@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" + +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" + +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== + dependencies: + "@webassemblyjs/ast" "1.14.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-3.0.1.tgz#76ac285b9658fa642ce238c276264589aa2b6b57" + integrity sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA== + +"@webpack-cli/info@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-3.0.1.tgz#3cff37fabb7d4ecaab6a8a4757d3826cf5888c63" + integrity sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ== + +"@webpack-cli/serve@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-3.0.1.tgz#bd8b1f824d57e30faa19eb78e4c0951056f72f00" + integrity sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.12.1, acorn@^8.14.0, acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +ajv@^8.0.0, ajv@^8.9.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-query@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + +asn1.js@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +assert@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + +autolinker@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-4.1.5.tgz#e0d45f04c41d62598bf80b809c422f732d3aafde" + integrity sha512-vEfYZPmvVOIuE567XBVCsx8SBgOYtjB2+S1iAaJ+HgH+DNjAcrHem2hmAeC9yaNGWayicv4yR+9UaJlkF3pvtw== + dependencies: + tslib "^2.8.1" + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-64@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a" + integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.2.tgz#3d8fed6796c24e177737f7cc5172ee04ef39ec99" + integrity sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw== + +bn.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-resolve@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-2.0.0.tgz#99b7304cb392f8d73dba741bb2d7da28c6d7842b" + integrity sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ== + dependencies: + resolve "^1.17.0" + +browserify-aes@^1.0.4, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.1.tgz#06e530907fe2949dc21fc3c2e2302e10b1437238" + integrity sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ== + dependencies: + bn.js "^5.2.1" + randombytes "^2.1.0" + safe-buffer "^5.2.1" + +browserify-sign@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.3.tgz#7afe4c01ec7ee59a89a558a4b75bd85ae62d4208" + integrity sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw== + dependencies: + bn.js "^5.2.1" + browserify-rsa "^4.1.0" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.5" + hash-base "~3.0" + inherits "^2.0.4" + parse-asn1 "^5.1.7" + readable-stream "^2.3.8" + safe-buffer "^5.2.1" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^4.24.0: + version "4.25.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111" + integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw== + dependencies: + caniuse-lite "^1.0.30001726" + electron-to-chromium "^1.5.173" + node-releases "^2.0.19" + update-browserslist-db "^1.1.3" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +caniuse-lite@^1.0.30001726: + version "1.0.30001726" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz#a15bd87d5a4bf01f6b6f70ae7c97fdfd28b5ae47" + integrity sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw== + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +chrome-trace-event@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7" + integrity sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +commander@^2.20.0, commander@^2.9.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +create-ecdh@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hash@~1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" + integrity sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + ripemd160 "^2.0.0" + sha.js "^2.4.0" + +create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.1.0.tgz#8f69355007ee182e47fa692ecbaa37a52e43c3d2" + integrity sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw== + dependencies: + node-fetch "^2.7.0" + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@^3.12.1: + version "3.12.1" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.1.tgz#bb8921bec9acc81633379aa8f52d69b0b69e0dac" + integrity sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ== + dependencies: + browserify-cipher "^1.0.1" + browserify-sign "^4.2.3" + create-ecdh "^4.0.4" + create-hash "^1.2.0" + create-hmac "^1.1.7" + diffie-hellman "^5.0.3" + hash-base "~3.0.4" + inherits "^2.0.4" + pbkdf2 "^3.1.2" + public-encrypt "^4.0.3" + randombytes "^2.1.0" + randomfill "^1.0.4" + +css-loader@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-7.1.2.tgz#64671541c6efe06b0e22e750503106bdd86880f8" + integrity sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.2.0" + semver "^7.5.4" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +debug@4.4.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +des.js@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +detect-indent@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-0.2.0.tgz#042914498979ac2d9f3c73e4ff3e6877d3bc92b6" + integrity sha512-C6jyrDu/eGH4KT0ZxAzijiH+ts5YLy7DqGFoDuHGxZjMOdjzRltp3jByySnpFBVIy4Em0ZkLN8tIV6mcREdw5A== + dependencies: + get-stdin "^0.1.0" + minimist "^0.1.0" + +diffie-hellman@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +domain-browser@4.22.0: + version "4.22.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.22.0.tgz#6ddd34220ec281f9a65d3386d267ddd35c491f9f" + integrity sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw== + +dts-bundle-webpack@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/dts-bundle-webpack/-/dts-bundle-webpack-1.0.2.tgz#c50439a89e71fd9e42800092561c05d5c3ea9ea6" + integrity sha512-/gBQBu5spW8BsGKyYwZeDb+gzDsipisf4Hg0ERPrrS0661cYajVUHARwvts/vfvG5wuv+p295byoNl2da+Re6w== + dependencies: + dts-bundle "^0.7.3" + +dts-bundle@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/dts-bundle/-/dts-bundle-0.7.3.tgz#372b7bb69c820782e6382f400739a69dced3d59a" + integrity sha512-EEAEuPRk8QyKhoN90NHTh+spSQujkkvOnKWUfuzpmC/fgryiWopL1SegSktx0UsoPfNidIGVDN7/AXpBDBv0WQ== + dependencies: + "@types/detect-indent" "0.1.30" + "@types/glob" "5.0.30" + "@types/mkdirp" "0.3.29" + "@types/node" "8.0.0" + commander "^2.9.0" + detect-indent "^0.2.0" + glob "^6.0.4" + mkdirp "^0.5.0" + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +electron-to-chromium@^1.5.173: + version "1.5.177" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz#db730d8254959184e65320a3a0b7edcd29c54f60" + integrity sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g== + +elliptic@^6.5.3, elliptic@^6.5.5: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +email-addresses@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-5.0.0.tgz#7ae9e7f58eef7d5e3e2c2c2d3ea49b78dc854fa6" + integrity sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +enhanced-resolve@^5.0.0, enhanced-resolve@^5.17.1: + version "5.18.2" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz#7903c5b32ffd4b2143eeb4b92472bd68effd5464" + integrity sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +envinfo@^7.14.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" + integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-module-lexer@^1.2.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +esbuild@^0.25.0: + version "0.25.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" + integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.5" + "@esbuild/android-arm" "0.25.5" + "@esbuild/android-arm64" "0.25.5" + "@esbuild/android-x64" "0.25.5" + "@esbuild/darwin-arm64" "0.25.5" + "@esbuild/darwin-x64" "0.25.5" + "@esbuild/freebsd-arm64" "0.25.5" + "@esbuild/freebsd-x64" "0.25.5" + "@esbuild/linux-arm" "0.25.5" + "@esbuild/linux-arm64" "0.25.5" + "@esbuild/linux-ia32" "0.25.5" + "@esbuild/linux-loong64" "0.25.5" + "@esbuild/linux-mips64el" "0.25.5" + "@esbuild/linux-ppc64" "0.25.5" + "@esbuild/linux-riscv64" "0.25.5" + "@esbuild/linux-s390x" "0.25.5" + "@esbuild/linux-x64" "0.25.5" + "@esbuild/netbsd-arm64" "0.25.5" + "@esbuild/netbsd-x64" "0.25.5" + "@esbuild/openbsd-arm64" "0.25.5" + "@esbuild/openbsd-x64" "0.25.5" + "@esbuild/sunos-x64" "0.25.5" + "@esbuild/win32-arm64" "0.25.5" + "@esbuild/win32-ia32" "0.25.5" + "@esbuild/win32-x64" "0.25.5" + +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.29.0: + version "9.30.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.30.0.tgz#fb0c655f5e28fc1b2f4050c28efa1876d78034fc" + integrity sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.0" + "@eslint/config-helpers" "^0.3.0" + "@eslint/core" "^0.14.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.30.0" + "@eslint/plugin-kit" "^0.3.1" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.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" + 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" + +esm-env@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/esm-env/-/esm-env-1.2.2.tgz#263c9455c55861f41618df31b20cb571fc20b75e" + integrity sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA== + +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrap@^1.4.8: + version "1.4.9" + resolved "https://registry.yarnpkg.com/esrap/-/esrap-1.4.9.tgz#350362c55d8c83b263edfb0fd48dac95162167de" + integrity sha512-3OMlcd0a03UGuZpPeUC1HxR3nA23l+HEyCiZw3b3FumJIN9KphoGzDJKMXI1S72jVS1dsenDyQC0kJlO1U9E1g== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +events@^3.0.0, events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-uri@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" + integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fdir@^6.4.4: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" + integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + +for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +foreground-child@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stdin@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-0.1.0.tgz#5998af24aafc802d15c82c685657eeb8b10d4a91" + integrity sha512-/WBu3IaQZxE3bs3BhBmR10ipDY4pjN+U4EZgXULa1eqKA0B/Lka/MVoAqhTVYBkkRlCrEGDOU9itrzIgm9Ksng== + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^11.0.0: + version "11.0.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.3.tgz#9d8087e6d72ddb3c4707b1d2778f80ea3eaefcd6" + integrity sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA== + dependencies: + foreground-child "^3.3.1" + jackspeak "^4.1.1" + minimatch "^10.0.3" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^2.0.0" + +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-16.2.0.tgz#19efcd1ddde2bd5efce128e5c2e441df1abc6f7c" + integrity sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg== + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hash-base@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" + integrity sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw== + dependencies: + inherits "^2.0.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash-base@~3.0, hash-base@~3.0.4: + version "3.0.5" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.5.tgz#52480e285395cf7fba17dc4c9e47acdc7f248a8a" + integrity sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== + +ical.js@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ical.js/-/ical.js-2.2.0.tgz#9c0c2d44c34e34104cc2dc8d24a2e13c0519ac9f" + integrity sha512-P8gjWkTEd5M/SEEvBVPPO/KC+V+HRNRZh3xfCDTVWmUTEfVbL8JaK5GTWS2MJ55aLMhfXhbh7kYzd0nrBARjsA== + +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.2.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +ignore@^7.0.0: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +is-arguments@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" + integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-function@^1.0.7: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== + dependencies: + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-reference@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.3.tgz#9ef7bf9029c70a67b2152da4adf57c23d718910f" + integrity sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw== + dependencies: + "@types/estree" "^1.0.6" + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-typed-array@^1.1.14, is-typed-array@^1.1.3: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isomorphic-timers-promises@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz#e4137c24dbc54892de8abae3a4b5c1ffff381598" + integrity sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ== + +jackspeak@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.1.tgz#96876030f450502047fc7e8c7fcf8ce8124e43ae" + integrity sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +locate-character@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-character/-/locate-character-3.0.0.tgz#0305c5b8744f61028ef5d01f444009e00779f974" + integrity sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lru-cache@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.1.0.tgz#afafb060607108132dbc1cf8ae661afb69486117" + integrity sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A== + +magic-string@^0.30.11, magic-string@^0.30.3: + version "0.30.17" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdn-data@2.21.0: + version "2.21.0" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.21.0.tgz#f3a495e8b1e60cb4fbeaf9136aefba2f987a56e1" + integrity sha512-+ZKPQezM5vYJIkCxaC+4DTnRrVZR1CgsKLu5zsQERQx6Tea8Y+wMx5A24rq8A8NepCeatIQufVAekKNgiBMsGQ== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.0, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +"minimatch@2 || 3", minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.3.tgz#cf7a0314a16c4d9ab73a7730a0e8e3c3502d47aa" + integrity sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw== + dependencies: + "@isaacs/brace-expansion" "^5.0.0" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" + integrity sha512-wR5Ipl99t0mTGwLjQJnBjrP/O7zBbLZqvA3aw32DmLx+nXHfWctUjzDjnDx09pX1Po86WFQazF9xUzfMea3Cnw== + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mkdirp@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mustache@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-polyfill-webpack-plugin@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/node-polyfill-webpack-plugin/-/node-polyfill-webpack-plugin-4.1.0.tgz#13115d0e3b1c99d978acffeb8cd3aab55d2a9203" + integrity sha512-b4ei444EKkOagG/yFqojrD3QTYM5IOU1f8tn9o6uwrG4qL+brI7oVhjPVd0ZL2xy+Z6CP5bu9w8XTvlWgiXHcw== + dependencies: + node-stdlib-browser "^1.3.0" + type-fest "^4.27.0" + +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + +node-stdlib-browser@^1.2.0, node-stdlib-browser@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.3.1.tgz#f41fa554f720a3df951e40339f4d92ac512222ac" + integrity sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw== + dependencies: + assert "^2.0.0" + browser-resolve "^2.0.0" + browserify-zlib "^0.2.0" + buffer "^5.7.1" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + create-require "^1.1.1" + crypto-browserify "^3.12.1" + domain-browser "4.22.0" + events "^3.0.0" + https-browserify "^1.0.0" + isomorphic-timers-promises "^1.0.1" + os-browserify "^0.3.0" + path-browserify "^1.0.1" + pkg-dir "^5.0.0" + process "^0.11.10" + punycode "^1.4.1" + querystring-es3 "^0.2.1" + readable-stream "^3.6.0" + stream-browserify "^3.0.0" + stream-http "^3.2.0" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.1" + url "^0.11.4" + util "^0.12.4" + vm-browserify "^1.0.1" + +npm-run-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-6.0.0.tgz#25cfdc4eae04976f3349c0b1afc089052c362537" + integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== + dependencies: + path-key "^4.0.0" + unicorn-magic "^0.3.0" + +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.7.tgz#73cdaaa822125f9647165625eb45f8a051d2df06" + integrity sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg== + dependencies: + asn1.js "^4.10.1" + browserify-aes "^1.2.0" + evp_bytestokey "^1.0.3" + hash-base "~3.0" + pbkdf2 "^3.1.2" + safe-buffer "^5.2.1" + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" + integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== + dependencies: + lru-cache "^11.0.0" + minipass "^7.1.2" + +pbkdf2@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.3.tgz#8be674d591d65658113424592a95d1517318dd4b" + integrity sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA== + dependencies: + create-hash "~1.1.3" + create-hmac "^1.1.7" + ripemd160 "=2.0.1" + safe-buffer "^5.2.1" + sha.js "^2.4.11" + to-buffer "^1.2.0" + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-dir@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== + dependencies: + find-up "^5.0.0" + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.5: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz#d150f43837831dae25e4085596e84f6f5d6ec368" + integrity sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^7.0.0" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" + integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== + dependencies: + postcss-selector-parser "^7.0.0" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" + integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.33, postcss@^8.5.3: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +public-encrypt@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@^6.12.3: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + +querystring-es3@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +readable-stream@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + 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" + +readable-stream@^3.5.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.17.0, resolve@^1.20.0: + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + dependencies: + is-core-module "^2.16.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rimraf@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-6.0.1.tgz#ffb8ad8844dd60332ab15f52bc104bc3ed71ea4e" + integrity sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A== + dependencies: + glob "^11.0.0" + package-json-from-dist "^1.0.0" + +ripemd160@=2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" + integrity sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w== + dependencies: + hash-base "^2.0.0" + inherits "^2.0.1" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rollup@^4.34.9: + version "4.44.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.44.1.tgz#641723932894e7acbe6052aea34b8e72ef8b7c8f" + integrity sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.44.1" + "@rollup/rollup-android-arm64" "4.44.1" + "@rollup/rollup-darwin-arm64" "4.44.1" + "@rollup/rollup-darwin-x64" "4.44.1" + "@rollup/rollup-freebsd-arm64" "4.44.1" + "@rollup/rollup-freebsd-x64" "4.44.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.44.1" + "@rollup/rollup-linux-arm-musleabihf" "4.44.1" + "@rollup/rollup-linux-arm64-gnu" "4.44.1" + "@rollup/rollup-linux-arm64-musl" "4.44.1" + "@rollup/rollup-linux-loongarch64-gnu" "4.44.1" + "@rollup/rollup-linux-powerpc64le-gnu" "4.44.1" + "@rollup/rollup-linux-riscv64-gnu" "4.44.1" + "@rollup/rollup-linux-riscv64-musl" "4.44.1" + "@rollup/rollup-linux-s390x-gnu" "4.44.1" + "@rollup/rollup-linux-x64-gnu" "4.44.1" + "@rollup/rollup-linux-x64-musl" "4.44.1" + "@rollup/rollup-win32-arm64-msvc" "4.44.1" + "@rollup/rollup-win32-ia32-msvc" "4.44.1" + "@rollup/rollup-win32-x64-msvc" "4.44.1" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +sax@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + +schema-utils@^4.3.0, schema-utils@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.2.tgz#0c10878bf4a73fd2b1dfd14b9462b26788c806ae" + integrity sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + +semver@^7.3.4, semver@^7.5.4, semver@^7.6.0: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + 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" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +source-map-js@^1.0.1, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +stream-browserify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + +stream-http@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" + integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1, strip-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +style-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-4.0.0.tgz#0ea96e468f43c69600011e0589cb05c44f3b17a5" + integrity sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svelte@^5, svelte@^5.34.8: + version "5.34.9" + resolved "https://registry.yarnpkg.com/svelte/-/svelte-5.34.9.tgz#c649e45821679c70c2c5cedf1ba1a2355dcb02bf" + integrity sha512-sld35zFpooaSRSj4qw8Vl/cyyK0/sLQq9qhJ7BGZo/Kd0ggYtEnvNYLlzhhoqYsYQzA0hJqkzt3RBO/8KoTZOg== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@jridgewell/sourcemap-codec" "^1.5.0" + "@sveltejs/acorn-typescript" "^1.0.5" + "@types/estree" "^1.0.5" + acorn "^8.12.1" + aria-query "^5.3.1" + axobject-query "^4.1.0" + clsx "^2.1.1" + esm-env "^1.2.1" + esrap "^1.4.8" + is-reference "^3.0.3" + locate-character "^3.0.0" + magic-string "^0.30.11" + zimmerframe "^1.1.2" + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.2.tgz#ab4984340d30cb9989a490032f086dbb8b56d872" + integrity sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg== + +terser-webpack-plugin@^5.3.11: + version "5.3.14" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz#9031d48e57ab27567f02ace85c7d690db66c3e06" + integrity sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.25" + jest-worker "^27.4.5" + schema-utils "^4.3.0" + serialize-javascript "^6.0.2" + terser "^5.31.1" + +terser@^5.31.1: + version "5.43.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.43.1.tgz#88387f4f9794ff1a29e7ad61fb2932e25b4fdb6d" + integrity sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.14.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +timers-browserify@^2.0.4: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + +timezones-ical-library@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/timezones-ical-library/-/timezones-ical-library-1.10.0.tgz#7cbfcae7d670c28f1ce2b2a0fcc04995d45c0799" + integrity sha512-aSwylC0FyyxMqMjkuaYz56HBhhooYabGT74CbTuY1uOeIcBXSQTXf+u/mTR0MWJFPQDe21REjex+4wt0OdFDpA== + +tiny-invariant@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + +tinyglobby@^0.2.13: + version "0.2.14" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +to-buffer@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.1.tgz#2ce650cdb262e9112a18e65dc29dcb513c8155e0" + integrity sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ== + dependencies: + isarray "^2.0.5" + safe-buffer "^5.2.1" + typed-array-buffer "^1.0.3" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + +ts-ics@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/ts-ics/-/ts-ics-2.1.8.tgz#801cdb1ab716e58187ab80f340440d7d79e85230" + integrity sha512-OxmvHHVe2mx1KPRODbtkguA/x4A5abqoDfEc3/+78+jJ0ilrdgXahkf773dn2ZmMGnK4+d5/hWSX2N1HsPyI+w== + dependencies: + "@standard-schema/spec" "^1.0.0" + +ts-loader@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.5.2.tgz#1f3d7f4bb709b487aaa260e8f19b301635d08020" + integrity sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + source-map "^0.7.4" + +tsdav@^2.1.4: + version "2.1.5" + resolved "https://registry.yarnpkg.com/tsdav/-/tsdav-2.1.5.tgz#6658e57a8fd3b56030c226d2a835336eb02207b3" + integrity sha512-ZUNFysY8Dr11I7aVpFmjk6apvHCMSmOPKGz8Wc1F/8BPn/kVS50LR2T8eCsdF5u+h8hrZrQhC0HWD5d2CCov+g== + dependencies: + base-64 "1.0.0" + cross-fetch "4.1.0" + debug "4.4.1" + xml-js "1.6.11" + +tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tty-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^4.27.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + +typescript-eslint@^8.35.0: + version "8.35.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.35.0.tgz#65afcdde973614b8f44fa89293919420ca9b904e" + integrity sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A== + dependencies: + "@typescript-eslint/eslint-plugin" "8.35.0" + "@typescript-eslint/parser" "8.35.0" + "@typescript-eslint/utils" "8.35.0" + +typescript@^5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== + +unicorn-magic@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz#4efd45c85a69e0dd576d25532fbfa22aa5c8a104" + integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== + +update-browserslist-db@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.4.tgz#adca77b3562d56b72746e76b330b7f27b6721f3c" + integrity sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg== + dependencies: + punycode "^1.4.1" + qs "^6.12.3" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@^0.12.4, util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +vite-plugin-checker@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/vite-plugin-checker/-/vite-plugin-checker-0.9.3.tgz#f6665dba3d6fa8ef5a559e35e546abc33e5f6074" + integrity sha512-Tf7QBjeBtG7q11zG0lvoF38/2AVUzzhMNu+Wk+mcsJ00Rk/FpJ4rmUviVJpzWkagbU13cGXvKpt7CMiqtxVTbQ== + dependencies: + "@babel/code-frame" "^7.27.1" + chokidar "^4.0.3" + npm-run-path "^6.0.0" + picocolors "^1.1.1" + picomatch "^4.0.2" + strip-ansi "^7.1.0" + tiny-invariant "^1.3.3" + tinyglobby "^0.2.13" + vscode-uri "^3.1.0" + +vite-plugin-node-polyfills@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.23.0.tgz#99d0d1524fa75ce5c7bb1fc8af30283379e9c684" + integrity sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w== + dependencies: + "@rollup/plugin-inject" "^5.0.5" + node-stdlib-browser "^1.2.0" + +vite@^6.3.5: + version "6.3.5" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.5.tgz#fec73879013c9c0128c8d284504c6d19410d12a3" + integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +vscode-uri@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +watchpack@^2.4.1: + version "2.4.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.4.tgz#473bda72f0850453da6425081ea46fc0d7602947" + integrity sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-cli@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-6.0.1.tgz#a1ce25da5ba077151afd73adfa12e208e5089207" + integrity sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw== + dependencies: + "@discoveryjs/json-ext" "^0.6.1" + "@webpack-cli/configtest" "^3.0.1" + "@webpack-cli/info" "^3.0.1" + "@webpack-cli/serve" "^3.0.1" + colorette "^2.0.14" + commander "^12.1.0" + cross-spawn "^7.0.3" + envinfo "^7.14.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^6.0.1" + +webpack-merge@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-6.0.1.tgz#50c776868e080574725abc5869bd6e4ef0a16c6a" + integrity sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.1" + +webpack-sources@^3.2.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.3.3.tgz#d4bf7f9909675d7a070ff14d0ef2a4f3c982c723" + integrity sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg== + +webpack@^5.99.9: + version "5.99.9" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.99.9.tgz#d7de799ec17d0cce3c83b70744b4aedb537d8247" + integrity sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg== + dependencies: + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + "@webassemblyjs/ast" "^1.14.1" + "@webassemblyjs/wasm-edit" "^1.14.1" + "@webassemblyjs/wasm-parser" "^1.14.1" + acorn "^8.14.0" + browserslist "^4.24.0" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.1" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^4.3.2" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.11" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-typed-array@^1.1.16, which-typed-array@^1.1.2: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xml-js@1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" + integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== + dependencies: + sax "^1.2.4" + +xtend@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zimmerframe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/zimmerframe/-/zimmerframe-1.1.2.tgz#5b75f1fa83b07ae2a428d51e50f58e2ae6855e5e" + integrity sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w== diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock new file mode 100644 index 0000000..c62ff84 --- /dev/null +++ b/src/frontend/yarn.lock @@ -0,0 +1,8473 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.27.2": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.5.tgz#a8a4962e1567121ac0b3b487f52107443b455c7f" + integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.24.4", "@babel/core@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.5.tgz#4c81b35e51e1b734f510c99b07dfbc7bbbb48f7e" + integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.4" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.28.5", "@babel/generator@^7.7.2": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.5.tgz#712722d5e50f44d07bc7ac9fe84438742dd61298" + integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== + dependencies: + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== + dependencies: + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-transforms@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" + integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.28.3" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.27.1", "@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helpers@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.4.tgz#fe07274742e95bdf7cf1443593eeb8926ab63827" + integrity sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w== + dependencies: + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.4" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.4", "@babel/parser@^7.27.2", "@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== + dependencies: + "@babel/types" "^7.28.5" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" + integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx-self@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz#af678d8506acf52c577cac73ff7fe6615c85fc92" + integrity sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx-source@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz#dcfe2c24094bb757bf73960374e7c55e434f19f0" + integrity sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.24.5", "@babel/runtime@^7.27.6", "@babel/runtime@^7.9.2": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + +"@babel/template@^7.27.2", "@babel/template@^7.3.3": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.5.tgz#450cab9135d21a7a2ca9d2d35aa05c20e68c360b" + integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" + debug "^4.3.1" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.28.2", "@babel/types@^7.28.4", "@babel/types@^7.28.5", "@babel/types@^7.3.3": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@dnd-kit/accessibility@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz#3b4202bd6bb370a0730f6734867785919beac6af" + integrity sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw== + dependencies: + tslib "^2.0.0" + +"@dnd-kit/core@6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-6.3.1.tgz#4c36406a62c7baac499726f899935f93f0e6d003" + integrity sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ== + dependencies: + "@dnd-kit/accessibility" "^3.1.1" + "@dnd-kit/utilities" "^3.2.2" + tslib "^2.0.0" + +"@dnd-kit/modifiers@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz#96a0280c77b10c716ef79d9792ce7ad04370771d" + integrity sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw== + dependencies: + "@dnd-kit/utilities" "^3.2.2" + tslib "^2.0.0" + +"@dnd-kit/sortable@10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@dnd-kit/sortable/-/sortable-10.0.0.tgz#1f9382b90d835cd5c65d92824fa9dafb78c4c3e8" + integrity sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg== + dependencies: + "@dnd-kit/utilities" "^3.2.2" + tslib "^2.0.0" + +"@dnd-kit/utilities@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@dnd-kit/utilities/-/utilities-3.2.2.tgz#5a32b6af356dc5f74d61b37d6f7129a4040ced7b" + integrity sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg== + dependencies: + tslib "^2.0.0" + +"@emnapi/core@^1.4.3": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.7.1.tgz#3a79a02dbc84f45884a1806ebb98e5746bdfaac4" + integrity sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.7.1.tgz#a73784e23f5d57287369c808197288b52276b791" + integrity sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd" + integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.8.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + +"@eslint/config-array@^0.19.0": + version "0.19.2" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" + integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== + dependencies: + "@eslint/object-schema" "^2.1.7" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/core@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" + integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" + integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" + integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== + 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" + +"@eslint/eslintrc@^3.2.0", "@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + 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" + +"@eslint/js@9.20.0": + version "9.20.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" + integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== + +"@eslint/js@9.39.1", "@eslint/js@^9.25.0": + version "9.39.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.1.tgz#0dd59c3a9f40e3f1882975c321470969243e0164" + integrity sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw== + +"@eslint/object-schema@^2.1.6", "@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== + +"@eslint/plugin-kit@^0.2.5": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" + integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== + dependencies: + "@eslint/core" "^0.13.0" + levn "^0.4.1" + +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== + dependencies: + "@eslint/core" "^0.17.0" + levn "^0.4.1" + +"@fontsource-variable/roboto-flex@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@fontsource-variable/roboto-flex/-/roboto-flex-5.2.5.tgz#38368ea754697c2fdf08df11b06e8b6d391ff4c1" + integrity sha512-yrZ9rWNvfM4IBqJSpoFV4wC1GaKNwpzhihyBke+N3WiA0Y7LYxwj6kvvHgecabVIHFL3ZZJTwj3KcKOCyASFPg== + +"@fontsource/material-icons-outlined@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@fontsource/material-icons-outlined/-/material-icons-outlined-5.2.5.tgz#16b4b2a8dcd1fbd69d4182792a65f7b41b8cb230" + integrity sha512-soAUWorSKrLN0a7wk74pedV0ZxhLaMD40DuUTMIqTpDcdJ/pxaG+/OcXtMEzx2+5K5FwL7yS525ZInAzPG051Q== + +"@fontsource/material-icons@5.2.5": + version "5.2.5" + resolved "https://registry.yarnpkg.com/@fontsource/material-icons/-/material-icons-5.2.5.tgz#cdb9dd23c0da4b021c866dc529ed4c203414ec3c" + integrity sha512-9k0LBRVgResIeD+vC/epYmm/awN2k2L8twwEtUWQ3FHluMi+7PbISOpXqksvfqPn9FJy4/KEeWOhFTR/SrbhNw== + +"@formatjs/ecma402-abstract@2.3.6": + version "2.3.6" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz#d6ca9d3579054fe1e1a0a0b5e872e0d64922e4e1" + integrity sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw== + dependencies: + "@formatjs/fast-memoize" "2.2.7" + "@formatjs/intl-localematcher" "0.6.2" + decimal.js "^10.4.3" + tslib "^2.8.0" + +"@formatjs/fast-memoize@2.2.7": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz#707f9ddaeb522a32f6715bb7950b0831f4cc7b15" + integrity sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ== + dependencies: + tslib "^2.8.0" + +"@formatjs/icu-messageformat-parser@2.11.4": + version "2.11.4" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz#63bd2cd82d08ae2bef55adeeb86486df68826f32" + integrity sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/icu-skeleton-parser" "1.8.16" + tslib "^2.8.0" + +"@formatjs/icu-skeleton-parser@1.8.16": + version "1.8.16" + resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz#13f81f6845c7cf6599623006aacaf7d6b4ad2970" + integrity sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + tslib "^2.8.0" + +"@formatjs/intl-localematcher@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz#e9ebe0b4082d7d48e5b2d753579fb7ece4eaefea" + integrity sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA== + dependencies: + tslib "^2.8.0" + +"@gouvfr-lasuite/integration@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@gouvfr-lasuite/integration/-/integration-1.0.2.tgz#ed0000f4b738c5a19bb60f5b80a9a2f5d9414234" + integrity sha512-npOotZQSyu6SffHiPP+jQVOkJ3qW2KE2cANhEK92sNLX9uZqQaCqljO5GhzsBmh0lB76fiXnrr9i8SIpnDUSZg== + +"@gouvfr-lasuite/ui-kit@0.18.4": + version "0.18.4" + resolved "https://registry.yarnpkg.com/@gouvfr-lasuite/ui-kit/-/ui-kit-0.18.4.tgz#536a8e1873d3eca80d0734735d87d3eec4934938" + integrity sha512-D/oUexk73khJHBERr0l2S7uVMziUkPpnlrO2+JeTFGCr/7LwAdNBoxnbsVMBlb+S6WeNAkJQV53DmalTLs6GlA== + dependencies: + "@dnd-kit/core" "6.3.1" + "@dnd-kit/modifiers" "9.0.0" + "@dnd-kit/sortable" "10.0.0" + "@fontsource/material-icons" "5.2.5" + "@gouvfr-lasuite/integration" "1.0.2" + "@openfun/cunningham-react" "4.0.0" + "@types/node" "22.10.7" + clsx "2.1.1" + cmdk "1.0.4" + react-arborist "3.4.3" + react-aria-components "1.8.0" + react-resizable-panels "2.1.7" + react-stately "3.37.0" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.1", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + +"@img/colour@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@img/colour/-/colour-1.0.0.tgz#d2fabb223455a793bf3bf9c70de3d28526aa8311" + integrity sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw== + +"@img/sharp-darwin-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz#6e0732dcade126b6670af7aa17060b926835ea86" + integrity sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w== + optionalDependencies: + "@img/sharp-libvips-darwin-arm64" "1.2.4" + +"@img/sharp-darwin-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz#19bc1dd6eba6d5a96283498b9c9f401180ee9c7b" + integrity sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw== + optionalDependencies: + "@img/sharp-libvips-darwin-x64" "1.2.4" + +"@img/sharp-libvips-darwin-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz#2894c0cb87d42276c3889942e8e2db517a492c43" + integrity sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g== + +"@img/sharp-libvips-darwin-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz#e63681f4539a94af9cd17246ed8881734386f8cc" + integrity sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg== + +"@img/sharp-libvips-linux-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz#b1b288b36864b3bce545ad91fa6dadcf1a4ad318" + integrity sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw== + +"@img/sharp-libvips-linux-arm@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz#b9260dd1ebe6f9e3bdbcbdcac9d2ac125f35852d" + integrity sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A== + +"@img/sharp-libvips-linux-ppc64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz#4b83ecf2a829057222b38848c7b022e7b4d07aa7" + integrity sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA== + +"@img/sharp-libvips-linux-riscv64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz#880b4678009e5a2080af192332b00b0aaf8a48de" + integrity sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA== + +"@img/sharp-libvips-linux-s390x@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz#74f343c8e10fad821b38f75ced30488939dc59ec" + integrity sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ== + +"@img/sharp-libvips-linux-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz#df4183e8bd8410f7d61b66859a35edeab0a531ce" + integrity sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw== + +"@img/sharp-libvips-linuxmusl-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz#c8d6b48211df67137541007ee8d1b7b1f8ca8e06" + integrity sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw== + +"@img/sharp-libvips-linuxmusl-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz#be11c75bee5b080cbee31a153a8779448f919f75" + integrity sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg== + +"@img/sharp-linux-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz#7aa7764ef9c001f15e610546d42fce56911790cc" + integrity sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg== + optionalDependencies: + "@img/sharp-libvips-linux-arm64" "1.2.4" + +"@img/sharp-linux-arm@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz#5fb0c3695dd12522d39c3ff7a6bc816461780a0d" + integrity sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw== + optionalDependencies: + "@img/sharp-libvips-linux-arm" "1.2.4" + +"@img/sharp-linux-ppc64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz#9c213a81520a20caf66978f3d4c07456ff2e0813" + integrity sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA== + optionalDependencies: + "@img/sharp-libvips-linux-ppc64" "1.2.4" + +"@img/sharp-linux-riscv64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz#cdd28182774eadbe04f62675a16aabbccb833f60" + integrity sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw== + optionalDependencies: + "@img/sharp-libvips-linux-riscv64" "1.2.4" + +"@img/sharp-linux-s390x@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz#93eac601b9f329bb27917e0e19098c722d630df7" + integrity sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg== + optionalDependencies: + "@img/sharp-libvips-linux-s390x" "1.2.4" + +"@img/sharp-linux-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz#55abc7cd754ffca5002b6c2b719abdfc846819a8" + integrity sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ== + optionalDependencies: + "@img/sharp-libvips-linux-x64" "1.2.4" + +"@img/sharp-linuxmusl-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz#d6515ee971bb62f73001a4829b9d865a11b77086" + integrity sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" + +"@img/sharp-linuxmusl-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz#d97978aec7c5212f999714f2f5b736457e12ee9f" + integrity sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" + +"@img/sharp-wasm32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz#2f15803aa626f8c59dd7c9d0bbc766f1ab52cfa0" + integrity sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw== + dependencies: + "@emnapi/runtime" "^1.7.0" + +"@img/sharp-win32-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz#3706e9e3ac35fddfc1c87f94e849f1b75307ce0a" + integrity sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g== + +"@img/sharp-win32-ia32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz#0b71166599b049e032f085fb9263e02f4e4788de" + integrity sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg== + +"@img/sharp-win32-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8" + integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw== + +"@internationalized/date@3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@internationalized/date/-/date-3.8.0.tgz#24fb301029224351381aa87cba853ca1093af094" + integrity sha512-J51AJ0fEL68hE4CwGPa6E0PO6JDaVLd8aln48xFCSy7CZkZc96dGEGmLs2OEEbBxcsVZtfrqkXJwI2/MSG8yKw== + dependencies: + "@swc/helpers" "^0.5.0" + +"@internationalized/date@^3.10.0", "@internationalized/date@^3.8.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@internationalized/date/-/date-3.10.0.tgz#056db64a4facdf48c6937ad498a882a8151d640a" + integrity sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw== + dependencies: + "@swc/helpers" "^0.5.0" + +"@internationalized/message@^3.1.7", "@internationalized/message@^3.1.8": + version "3.1.8" + resolved "https://registry.yarnpkg.com/@internationalized/message/-/message-3.1.8.tgz#7181e8178f0868535f4507a573bf285e925832cb" + integrity sha512-Rwk3j/TlYZhn3HQ6PyXUV0XP9Uv42jqZGNegt0BXlxjE6G3+LwHjbQZAGHhCnCPdaA6Tvd3ma/7QzLlLkJxAWA== + dependencies: + "@swc/helpers" "^0.5.0" + intl-messageformat "^10.1.0" + +"@internationalized/number@^3.6.1", "@internationalized/number@^3.6.5": + version "3.6.5" + resolved "https://registry.yarnpkg.com/@internationalized/number/-/number-3.6.5.tgz#1103f2832ca8d9dd3e4eecf95733d497791dbbbe" + integrity sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g== + dependencies: + "@swc/helpers" "^0.5.0" + +"@internationalized/string@^3.2.6", "@internationalized/string@^3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@internationalized/string/-/string-3.2.7.tgz#76ae10f1e6e1fdaec7d0028a3f807d37a71bd2dd" + integrity sha512-D4OHBjrinH+PFZPvfCXvG28n2LSykWcJ7GIioQL+ok0LON15SdfoUssoHzzOUmVZLbRoREsQXVzA6r8JKsbP6A== + dependencies: + "@swc/helpers" "^0.5.0" + +"@isaacs/balanced-match@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29" + integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ== + +"@isaacs/brace-expansion@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz#4b3dabab7d8e75a429414a96bd67bf4c1d13e0f3" + integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA== + dependencies: + "@isaacs/balanced-match" "^4.0.1" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@microsoft/api-extractor-model@7.32.0": + version "7.32.0" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.32.0.tgz#623147407e9607b1467e7b8d24c32fd313cdd6ad" + integrity sha512-QIVJSreb8fGGJy1Qx0yzGVXxvHJN1WXgkFNHFheVv1iBJNqgvp+xeT3ienJmRwXmPPc5Es/cxBrXtKZJR3i7iw== + dependencies: + "@microsoft/tsdoc" "~0.16.0" + "@microsoft/tsdoc-config" "~0.18.0" + "@rushstack/node-core-library" "5.18.0" + +"@microsoft/api-extractor@^7.50.1": + version "7.55.0" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.55.0.tgz#1b3c3558111d9ba3c6e0adc948ca88d42906fa6e" + integrity sha512-TYc5OtAK/9E3HGgd2bIfSjQDYIwPc0dysf9rPiwXZGsq916I6W2oww9bhm1OxPOeg6rMfOX3PoroGd7oCryYog== + dependencies: + "@microsoft/api-extractor-model" "7.32.0" + "@microsoft/tsdoc" "~0.16.0" + "@microsoft/tsdoc-config" "~0.18.0" + "@rushstack/node-core-library" "5.18.0" + "@rushstack/rig-package" "0.6.0" + "@rushstack/terminal" "0.19.3" + "@rushstack/ts-command-line" "5.1.3" + diff "~8.0.2" + lodash "~4.17.15" + minimatch "10.0.3" + resolve "~1.22.1" + semver "~7.5.4" + source-map "~0.6.1" + typescript "5.8.2" + +"@microsoft/tsdoc-config@~0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.18.0.tgz#02fd9924b888053ecbc3c0385a24532bf2106c98" + integrity sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw== + dependencies: + "@microsoft/tsdoc" "0.16.0" + ajv "~8.12.0" + jju "~1.4.0" + resolve "~1.22.2" + +"@microsoft/tsdoc@0.16.0", "@microsoft/tsdoc@~0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz#2249090633e04063176863a050c8f0808d2b6d2b" + integrity sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA== + +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + +"@next/env@15.4.9": + version "15.4.9" + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.4.9.tgz#5caeeaf5f20cf2bf5176444f13d087963159031f" + integrity sha512-OYR0RulK5phnbxxzcLE4/ECgfx1PL3EHrDbjyelJ7jauaO+/Qvj5gG8JPMltB51CygC2KrZ0aAfYLjPYjYY17A== + +"@next/eslint-plugin-next@15.1.7": + version "15.1.7" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.7.tgz#f8593c714f51ac6d443fb298584954d5def4392b" + integrity sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ== + dependencies: + fast-glob "3.3.1" + +"@next/swc-darwin-arm64@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.4.8.tgz#f5030219421079036720b5948ea9de9bee02ac34" + integrity sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A== + +"@next/swc-darwin-x64@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.4.8.tgz#3fc796bd522aee30eff608448919e0ea1c1da7d1" + integrity sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw== + +"@next/swc-linux-arm64-gnu@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.4.8.tgz#5c7bf6a0de49c2b4c21bc8bdb3b5e431dd922c7d" + integrity sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw== + +"@next/swc-linux-arm64-musl@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.4.8.tgz#94e47838715e68a696b33295f4389a60bd8af00a" + integrity sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A== + +"@next/swc-linux-x64-gnu@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.4.8.tgz#4f9656e8bf9f28dac1970d6ff95a245014646417" + integrity sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA== + +"@next/swc-linux-x64-musl@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.4.8.tgz#c5c64e18370f54f6474e58bb01b12594a4ecdde6" + integrity sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA== + +"@next/swc-win32-arm64-msvc@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.4.8.tgz#722d18ed569bee9e4a6651acdc756f9633cbee1f" + integrity sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw== + +"@next/swc-win32-x64-msvc@15.4.8": + version "15.4.8" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.4.8.tgz#a29a53cd262ec5093b9ac24a5fd5e4540ec64eb4" + integrity sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nolyfill/is-core-module@1.0.39": + version "1.0.39" + resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" + integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== + +"@openfun/cunningham-react@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@openfun/cunningham-react/-/cunningham-react-4.0.0.tgz#5d273c72a2ced76cf060931b546238b7ee75c6ec" + integrity sha512-2JgIRDl2UE/PMcOrjjfxbhFRwEwF7JFAaPoN/Xjq+sOYHP6WasRxFRrkwhnuZ5ZU7lOpzaAFyPtkawoBF6GsEQ== + dependencies: + "@fontsource-variable/roboto-flex" "5.2.5" + "@fontsource/material-icons-outlined" "5.2.5" + "@internationalized/date" "3.8.0" + "@openfun/cunningham-tokens" "*" + "@react-aria/calendar" "3.8.0" + "@react-aria/datepicker" "3.14.2" + "@react-aria/i18n" "3.12.8" + "@react-stately/calendar" "3.8.0" + "@react-stately/datepicker" "3.14.0" + "@tanstack/react-table" "8.21.3" + "@types/react-modal" "3.16.3" + chromatic "11.28.2" + classnames "2.5.1" + downshift "9.0.9" + react-aria "3.39.0" + react-aria-components "1.8.0" + react-modal "3.16.3" + react-stately "3.37.0" + +"@openfun/cunningham-tokens@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@openfun/cunningham-tokens/-/cunningham-tokens-3.0.0.tgz#2346ebcb7d18a35cbbb1c4f4c501f238173a3c8c" + integrity sha512-YMLLL7CaQA1+kuSVxf3UgXNjdyeX6Dj2Kdlz/9+lX2ePm51rPxZsEGXWeUVafNLFH+T/zpsajiEzgJ9mBEJd5w== + dependencies: + chalk "4.1.2" + commander "13.1.0" + deepmerge "4.3.1" + figlet "1.8.1" + ts-node "10.9.2" + +"@parcel/watcher-android-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" + integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== + +"@parcel/watcher-darwin-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67" + integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== + +"@parcel/watcher-darwin-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8" + integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== + +"@parcel/watcher-freebsd-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b" + integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== + +"@parcel/watcher-linux-arm-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1" + integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== + +"@parcel/watcher-linux-arm-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e" + integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== + +"@parcel/watcher-linux-arm64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30" + integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== + +"@parcel/watcher-linux-arm64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2" + integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== + +"@parcel/watcher-linux-x64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e" + integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== + +"@parcel/watcher-linux-x64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee" + integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== + +"@parcel/watcher-win32-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243" + integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== + +"@parcel/watcher-win32-ia32@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6" + integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== + +"@parcel/watcher-win32-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947" + integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== + +"@parcel/watcher@^2.4.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200" + integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.1" + "@parcel/watcher-darwin-arm64" "2.5.1" + "@parcel/watcher-darwin-x64" "2.5.1" + "@parcel/watcher-freebsd-x64" "2.5.1" + "@parcel/watcher-linux-arm-glibc" "2.5.1" + "@parcel/watcher-linux-arm-musl" "2.5.1" + "@parcel/watcher-linux-arm64-glibc" "2.5.1" + "@parcel/watcher-linux-arm64-musl" "2.5.1" + "@parcel/watcher-linux-x64-glibc" "2.5.1" + "@parcel/watcher-linux-x64-musl" "2.5.1" + "@parcel/watcher-win32-arm64" "2.5.1" + "@parcel/watcher-win32-ia32" "2.5.1" + "@parcel/watcher-win32-x64" "2.5.1" + +"@playwright/test@1.56.1": + version "1.56.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.56.1.tgz#6e3bf3d0c90c5cf94bf64bdb56fd15a805c8bd3f" + integrity sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg== + dependencies: + playwright "1.56.1" + +"@posthog/core@1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@posthog/core/-/core-1.5.2.tgz#06f1277c5ac9a3d5a17bc3800172a392e594f44c" + integrity sha512-iedUP3EnOPPxTA2VaIrsrd29lSZnUV+ZrMnvY56timRVeZAXoYCkmjfIs3KBAsF8OUT5h1GXLSkoQdrV0r31OQ== + dependencies: + cross-spawn "^7.0.6" + +"@radix-ui/primitive@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.3.tgz#e2dbc13bdc5e4168f4334f75832d7bdd3e2de5ba" + integrity sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg== + +"@radix-ui/react-compose-refs@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz#a2c4c47af6337048ee78ff6dc0d090b390d2bb30" + integrity sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg== + +"@radix-ui/react-context@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36" + integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA== + +"@radix-ui/react-dialog@^1.1.2": + version "1.1.15" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz#1de3d7a7e9a17a9874d29c07f5940a18a119b632" + integrity sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw== + dependencies: + "@radix-ui/primitive" "1.1.3" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-context" "1.1.2" + "@radix-ui/react-dismissable-layer" "1.1.11" + "@radix-ui/react-focus-guards" "1.1.3" + "@radix-ui/react-focus-scope" "1.1.7" + "@radix-ui/react-id" "1.1.1" + "@radix-ui/react-portal" "1.1.9" + "@radix-ui/react-presence" "1.1.5" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-slot" "1.2.3" + "@radix-ui/react-use-controllable-state" "1.2.2" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + +"@radix-ui/react-dismissable-layer@1.1.11": + version "1.1.11" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz#e33ab6f6bdaa00f8f7327c408d9f631376b88b37" + integrity sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg== + dependencies: + "@radix-ui/primitive" "1.1.3" + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-callback-ref" "1.1.1" + "@radix-ui/react-use-escape-keydown" "1.1.1" + +"@radix-ui/react-focus-guards@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz#2a5669e464ad5fde9f86d22f7fdc17781a4dfa7f" + integrity sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw== + +"@radix-ui/react-focus-scope@1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz#dfe76fc103537d80bf42723a183773fd07bfb58d" + integrity sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-callback-ref" "1.1.1" + +"@radix-ui/react-id@1.1.1", "@radix-ui/react-id@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.1.tgz#1404002e79a03fe062b7e3864aa01e24bd1471f7" + integrity sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-portal@1.1.9": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.9.tgz#14c3649fe48ec474ac51ed9f2b9f5da4d91c4472" + integrity sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ== + dependencies: + "@radix-ui/react-primitive" "2.1.3" + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-presence@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.5.tgz#5d8f28ac316c32f078afce2996839250c10693db" + integrity sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.2" + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-primitive@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz#db9b8bcff49e01be510ad79893fb0e4cda50f1bc" + integrity sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ== + dependencies: + "@radix-ui/react-slot" "1.2.3" + +"@radix-ui/react-primitive@^2.0.0": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz#2626ea309ebd63bf5767d3e7fc4081f81b993df0" + integrity sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg== + dependencies: + "@radix-ui/react-slot" "1.2.4" + +"@radix-ui/react-slot@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.3.tgz#502d6e354fc847d4169c3bc5f189de777f68cfe1" + integrity sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A== + dependencies: + "@radix-ui/react-compose-refs" "1.1.2" + +"@radix-ui/react-slot@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.4.tgz#63c0ba05fdf90cc49076b94029c852d7bac1fb83" + integrity sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.2" + +"@radix-ui/react-use-callback-ref@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz#62a4dba8b3255fdc5cc7787faeac1c6e4cc58d40" + integrity sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg== + +"@radix-ui/react-use-controllable-state@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz#905793405de57d61a439f4afebbb17d0645f3190" + integrity sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg== + dependencies: + "@radix-ui/react-use-effect-event" "0.0.2" + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-use-effect-event@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz#090cf30d00a4c7632a15548512e9152217593907" + integrity sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.1" + +"@radix-ui/react-use-escape-keydown@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz#b3fed9bbea366a118f40427ac40500aa1423cc29" + integrity sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.1" + +"@radix-ui/react-use-layout-effect@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz#0c4230a9eed49d4589c967e2d9c0d9d60a23971e" + integrity sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ== + +"@react-aria/autocomplete@3.0.0-beta.2": + version "3.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@react-aria/autocomplete/-/autocomplete-3.0.0-beta.2.tgz#61fc21cde05206e9a90f32378f25d13f5424366c" + integrity sha512-oxsFCIGj5yooQkZzdqjvsdfr9fOlmAq4v6njIOAyQFsta3H0yQiv+YU3XnrnCBxVX+Mz/mZtZgfhAA9JBDukHg== + dependencies: + "@react-aria/combobox" "^3.12.2" + "@react-aria/focus" "^3.20.2" + "@react-aria/i18n" "^3.12.8" + "@react-aria/interactions" "^3.25.0" + "@react-aria/listbox" "^3.14.3" + "@react-aria/searchfield" "^3.8.3" + "@react-aria/textfield" "^3.17.2" + "@react-aria/utils" "^3.28.2" + "@react-stately/autocomplete" "3.0.0-beta.1" + "@react-stately/combobox" "^3.10.4" + "@react-types/autocomplete" "3.0.0-alpha.30" + "@react-types/button" "^3.12.0" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-aria/breadcrumbs@^3.5.23", "@react-aria/breadcrumbs@^3.5.29": + version "3.5.29" + resolved "https://registry.yarnpkg.com/@react-aria/breadcrumbs/-/breadcrumbs-3.5.29.tgz#bfc1e953eccd7393bd457f1c9698a928142f0fc7" + integrity sha512-rKS0dryllaZJqrr3f/EAf2liz8CBEfmL5XACj+Z1TAig6GIYe1QuA3BtkX0cV9OkMugXdX8e3cbA7nD10ORRqg== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/link" "^3.8.6" + "@react-aria/utils" "^3.31.0" + "@react-types/breadcrumbs" "^3.7.17" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/button@^3.13.0", "@react-aria/button@^3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@react-aria/button/-/button-3.14.2.tgz#9dcd2fa53e7968a563b4898ace3360c85ccc22f5" + integrity sha512-VbLIA+Kd6f/MDjd+TJBUg2+vNDw66pnvsj2E4RLomjI9dfBuN7d+Yo2UnsqKVyhePjCUZ6xxa2yDuD63IOSIYA== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/toolbar" "3.0.0-beta.21" + "@react-aria/utils" "^3.31.0" + "@react-stately/toggle" "^3.9.2" + "@react-types/button" "^3.14.1" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/calendar@3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@react-aria/calendar/-/calendar-3.8.0.tgz#8f210d2ecfd89a8020f5568fdf2014a8e6c62a46" + integrity sha512-9vms/fWjJPZkJcMxciwWWOjGy/Q0nqI6FV0pYbMZbqepkzglEaVd98kl506r/4hLhWKwLdTfqCgbntRecj8jBg== + dependencies: + "@internationalized/date" "^3.8.0" + "@react-aria/i18n" "^3.12.8" + "@react-aria/interactions" "^3.25.0" + "@react-aria/live-announcer" "^3.4.2" + "@react-aria/utils" "^3.28.2" + "@react-stately/calendar" "^3.8.0" + "@react-types/button" "^3.12.0" + "@react-types/calendar" "^3.7.0" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-aria/calendar@^3.8.0", "@react-aria/calendar@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-aria/calendar/-/calendar-3.9.2.tgz#4b6e428ee3fb81f5729cb80193b9d4ba9b26d5f1" + integrity sha512-uSLxLgOPRnEU4Jg59lAhUVA+uDx/55NBg4lpfsP2ynazyiJ5LCXmYceJi+VuOqMml7d9W0dB87OldOeLdIxYVA== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/utils" "^3.31.0" + "@react-stately/calendar" "^3.9.0" + "@react-types/button" "^3.14.1" + "@react-types/calendar" "^3.8.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/checkbox@^3.15.4", "@react-aria/checkbox@^3.16.2": + version "3.16.2" + resolved "https://registry.yarnpkg.com/@react-aria/checkbox/-/checkbox-3.16.2.tgz#b1a3310d327826fe354625c332f3b80acb025a39" + integrity sha512-29Mj9ZqXioJ0bcMnNGooHztnTau5pikZqX3qCRj5bYR3by/ZFFavYoMroh9F7s/MbFm/tsKX+Sf02lYFEdXRjA== + dependencies: + "@react-aria/form" "^3.1.2" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/toggle" "^3.12.2" + "@react-aria/utils" "^3.31.0" + "@react-stately/checkbox" "^3.7.2" + "@react-stately/form" "^3.2.2" + "@react-stately/toggle" "^3.9.2" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/collections@3.0.0-rc.0": + version "3.0.0-rc.0" + resolved "https://registry.yarnpkg.com/@react-aria/collections/-/collections-3.0.0-rc.0.tgz#d0a906f4a4582a91b6ad866a58fbe2ef1713b15e" + integrity sha512-WcRcE3wKtbprOJlBaMbdYS5Suu2KIGq1gVT2fLXVbmDY0CjGemqp2m5aDblQOO8pxvsAqHV8pyznkhANTnK1CQ== + dependencies: + "@react-aria/interactions" "^3.25.0" + "@react-aria/ssr" "^3.9.8" + "@react-aria/utils" "^3.28.2" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + use-sync-external-store "^1.4.0" + +"@react-aria/color@^3.0.6", "@react-aria/color@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-aria/color/-/color-3.1.2.tgz#9ee2a86e4cf4622ca8ff78bddd34a2bf1bdcdd34" + integrity sha512-jCC+Q7rAQGLQBkHjkPAeDuGYuMbc4neifjlNRiyZ9as1z4gg63H8MteoWYYk6K4vCKKxSixgt8MfI29XWMOWPQ== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/numberfield" "^3.12.2" + "@react-aria/slider" "^3.8.2" + "@react-aria/spinbutton" "^3.6.19" + "@react-aria/textfield" "^3.18.2" + "@react-aria/utils" "^3.31.0" + "@react-aria/visually-hidden" "^3.8.28" + "@react-stately/color" "^3.9.2" + "@react-stately/form" "^3.2.2" + "@react-types/color" "^3.1.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/combobox@^3.12.2", "@react-aria/combobox@^3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@react-aria/combobox/-/combobox-3.14.0.tgz#1e6c55a319d367d6a0a9e19f2bd68d3a9a0c8b9a" + integrity sha512-z4ro0Hma//p4nL2IJx5iUa7NwxeXbzSoZ0se5uTYjG1rUUMszg+wqQh/AQoL+eiULn7rs18JY9wwNbVIkRNKWA== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/listbox" "^3.15.0" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/menu" "^3.19.3" + "@react-aria/overlays" "^3.30.0" + "@react-aria/selection" "^3.26.0" + "@react-aria/textfield" "^3.18.2" + "@react-aria/utils" "^3.31.0" + "@react-stately/collections" "^3.12.8" + "@react-stately/combobox" "^3.12.0" + "@react-stately/form" "^3.2.2" + "@react-types/button" "^3.14.1" + "@react-types/combobox" "^3.13.9" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/datepicker@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@react-aria/datepicker/-/datepicker-3.14.2.tgz#db1efa94edc86b57950cf32cbfd252b206653fab" + integrity sha512-O7fdzcqIJ7i/+8SGYvx4tloTZgK4Ws8OChdbFcd2rZoRPqxM50M6J+Ota8hTet2wIhojUXnM3x2na3EvoucBXA== + dependencies: + "@internationalized/date" "^3.8.0" + "@internationalized/number" "^3.6.1" + "@internationalized/string" "^3.2.6" + "@react-aria/focus" "^3.20.2" + "@react-aria/form" "^3.0.15" + "@react-aria/i18n" "^3.12.8" + "@react-aria/interactions" "^3.25.0" + "@react-aria/label" "^3.7.17" + "@react-aria/spinbutton" "^3.6.14" + "@react-aria/utils" "^3.28.2" + "@react-stately/datepicker" "^3.14.0" + "@react-stately/form" "^3.1.3" + "@react-types/button" "^3.12.0" + "@react-types/calendar" "^3.7.0" + "@react-types/datepicker" "^3.12.0" + "@react-types/dialog" "^3.5.17" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-aria/datepicker@^3.14.2", "@react-aria/datepicker@^3.15.2": + version "3.15.2" + resolved "https://registry.yarnpkg.com/@react-aria/datepicker/-/datepicker-3.15.2.tgz#22bca8cfdd00e32a42f8e53b35e5ba7e886f047d" + integrity sha512-th078hyNqPf4P2K10su/y32zPDjs3lOYVdHvsL9/+5K1dnTvLHCK5vgUyLuyn8FchhF7cmHV49D+LZVv65PEpQ== + dependencies: + "@internationalized/date" "^3.10.0" + "@internationalized/number" "^3.6.5" + "@internationalized/string" "^3.2.7" + "@react-aria/focus" "^3.21.2" + "@react-aria/form" "^3.1.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/spinbutton" "^3.6.19" + "@react-aria/utils" "^3.31.0" + "@react-stately/datepicker" "^3.15.2" + "@react-stately/form" "^3.2.2" + "@react-types/button" "^3.14.1" + "@react-types/calendar" "^3.8.0" + "@react-types/datepicker" "^3.13.2" + "@react-types/dialog" "^3.5.22" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/dialog@^3.5.24", "@react-aria/dialog@^3.5.31": + version "3.5.31" + resolved "https://registry.yarnpkg.com/@react-aria/dialog/-/dialog-3.5.31.tgz#1c1682a89dd6a4c6bc7bb0e58ea78eb6f2750a65" + integrity sha512-inxQMyrzX0UBW9Mhraq0nZ4HjHdygQvllzloT1E/RlDd61lr3RbmJR6pLsrbKOTtSvDIBJpCso1xEdHCFNmA0Q== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/overlays" "^3.30.0" + "@react-aria/utils" "^3.31.0" + "@react-types/dialog" "^3.5.22" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/disclosure@^3.0.4", "@react-aria/disclosure@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@react-aria/disclosure/-/disclosure-3.1.0.tgz#c08a0f9696fa80ca69de78f37c8bf0b65a7a9397" + integrity sha512-5996BeBpnj+yKXYysz+UuhFQxGFPvaZZ3zNBd052wz/i+TVFVGSqqYJ6cwZyO1AfBR8zOT0ZIiK4EC3ETwSvtQ== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-stately/disclosure" "^3.0.8" + "@react-types/button" "^3.14.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/dnd@^3.11.3", "@react-aria/dnd@^3.9.2": + version "3.11.3" + resolved "https://registry.yarnpkg.com/@react-aria/dnd/-/dnd-3.11.3.tgz#438b4603ef9b2560775ea02b64ea3dcdf15bf474" + integrity sha512-MyTziciik1Owz3rqDghu0K3ZtTFvmj/R2ZsLDwbU9N4hKqGX/BKnrI8SytTn8RDqVv5LmA/GhApLngiupTAsXw== + dependencies: + "@internationalized/string" "^3.2.7" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/overlays" "^3.30.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/collections" "^3.12.8" + "@react-stately/dnd" "^3.7.1" + "@react-types/button" "^3.14.1" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/focus@^3.20.2", "@react-aria/focus@^3.21.2": + version "3.21.2" + resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.21.2.tgz#3ce90450c3ee69f11c0647b4717c26d10941231c" + integrity sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-aria/form@^3.0.15", "@react-aria/form@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-aria/form/-/form-3.1.2.tgz#e0aeb608d309594a59f12a7b05eb7374f2033a07" + integrity sha512-R3i7L7Ci61PqZQvOrnL9xJeWEbh28UkTVgkj72EvBBn39y4h7ReH++0stv7rRs8p5ozETSKezBbGfu4UsBewWw== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/form" "^3.2.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/grid@^3.14.5": + version "3.14.5" + resolved "https://registry.yarnpkg.com/@react-aria/grid/-/grid-3.14.5.tgz#fccd1e3b64cdad7b17aff0dada6da64df0cd1d8c" + integrity sha512-XHw6rgjlTqc85e3zjsWo3U0EVwjN5MOYtrolCKc/lc2ItNdcY3OlMhpsU9+6jHwg/U3VCSWkGvwAz9hg7krd8Q== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/collections" "^3.12.8" + "@react-stately/grid" "^3.11.6" + "@react-stately/selection" "^3.20.6" + "@react-types/checkbox" "^3.10.2" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/gridlist@^3.12.0", "@react-aria/gridlist@^3.14.1": + version "3.14.1" + resolved "https://registry.yarnpkg.com/@react-aria/gridlist/-/gridlist-3.14.1.tgz#4aa636ad1342f859dc5ce1a350211535ae5ae424" + integrity sha512-keS03Am07aOn7RuNaRsMOyh0jscyhDn95asCVy4lxhl9A9TFk1Jw0o2L6q6cWRj1gFiKeacj/otG5H8ZKQQ2Wg== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/grid" "^3.14.5" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/list" "^3.13.1" + "@react-stately/tree" "^3.9.3" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/i18n@3.12.8": + version "3.12.8" + resolved "https://registry.yarnpkg.com/@react-aria/i18n/-/i18n-3.12.8.tgz#43d534f04d3bfdef674ba94527cf7532875d8fc8" + integrity sha512-V/Nau9WuwTwxfFffQL4URyKyY2HhRlu9zmzkF2Hw/j5KmEQemD+9jfaLueG2CJu85lYL06JrZXUdnhZgKnqMkA== + dependencies: + "@internationalized/date" "^3.8.0" + "@internationalized/message" "^3.1.7" + "@internationalized/number" "^3.6.1" + "@internationalized/string" "^3.2.6" + "@react-aria/ssr" "^3.9.8" + "@react-aria/utils" "^3.28.2" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-aria/i18n@^3.12.13", "@react-aria/i18n@^3.12.8": + version "3.12.13" + resolved "https://registry.yarnpkg.com/@react-aria/i18n/-/i18n-3.12.13.tgz#7c920d131cd07d4d5af21bd33ea7a5da0ce2ad11" + integrity sha512-YTM2BPg0v1RvmP8keHenJBmlx8FXUKsdYIEX7x6QWRd1hKlcDwphfjzvt0InX9wiLiPHsT5EoBTpuUk8SXc0Mg== + dependencies: + "@internationalized/date" "^3.10.0" + "@internationalized/message" "^3.1.8" + "@internationalized/number" "^3.6.5" + "@internationalized/string" "^3.2.7" + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/interactions@^3.25.0", "@react-aria/interactions@^3.25.6": + version "3.25.6" + resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.25.6.tgz#6fdf287337c5e4285045c35cf94b2ec8ae3b3a49" + integrity sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-stately/flags" "^3.1.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/label@^3.7.17", "@react-aria/label@^3.7.22": + version "3.7.22" + resolved "https://registry.yarnpkg.com/@react-aria/label/-/label-3.7.22.tgz#13fbf1d568c37becca4652e5c5d0b490c29e5e52" + integrity sha512-jLquJeA5ZNqDT64UpTc9XJ7kQYltUlNcgxZ37/v4mHe0UZ7QohCKdKQhXHONb0h2jjNUpp2HOZI8J9++jOpzxA== + dependencies: + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/landmark@^3.0.2", "@react-aria/landmark@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@react-aria/landmark/-/landmark-3.0.7.tgz#6ffc06c870018f6ead456f6f67cccebd655910f0" + integrity sha512-t8c610b8hPLS6Vwv+rbuSyljZosI1s5+Tosfa0Fk4q7d+Ex6Yj7hLfUFy59GxZAufhUYfGX396fT0gPqAbU1tg== + dependencies: + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + use-sync-external-store "^1.4.0" + +"@react-aria/link@^3.8.0", "@react-aria/link@^3.8.6": + version "3.8.6" + resolved "https://registry.yarnpkg.com/@react-aria/link/-/link-3.8.6.tgz#522c246b9fcf62fbe75f9c07d056d6b984523143" + integrity sha512-7F7UDJnwbU9IjfoAdl6f3Hho5/WB7rwcydUOjUux0p7YVWh/fTjIFjfAGyIir7MJhPapun1D0t97QQ3+8jXVcg== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-types/link" "^3.6.5" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/listbox@^3.14.3", "@react-aria/listbox@^3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@react-aria/listbox/-/listbox-3.15.0.tgz#4218e24c20ec68069f51175c57fa2bf55b1acc46" + integrity sha512-Ub1Wu79R9sgxM7h4HeEdjOgOKDHwduvYcnDqsSddGXgpkL8ADjsy2YUQ0hHY5VnzA4BxK36bLp4mzSna8Qvj1w== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/collections" "^3.12.8" + "@react-stately/list" "^3.13.1" + "@react-types/listbox" "^3.7.4" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/live-announcer@^3.4.2", "@react-aria/live-announcer@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@react-aria/live-announcer/-/live-announcer-3.4.4.tgz#0e6533940222208b323b71d56ac8e115b2121e6a" + integrity sha512-PTTBIjNRnrdJOIRTDGNifY2d//kA7GUAwRFJNOEwSNG4FW+Bq9awqLiflw0JkpyB0VNIwou6lqKPHZVLsGWOXA== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-aria/menu@^3.18.2", "@react-aria/menu@^3.19.3": + version "3.19.3" + resolved "https://registry.yarnpkg.com/@react-aria/menu/-/menu-3.19.3.tgz#65a6dc14b27648be611bf28ab4bbcd2823b612a8" + integrity sha512-52fh8y8b2776R2VrfZPpUBJYC9oTP7XDy+zZuZTxPEd7Ywk0JNUl5F92y6ru22yPkS13sdhrNM/Op+V/KulmAg== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/overlays" "^3.30.0" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/collections" "^3.12.8" + "@react-stately/menu" "^3.9.8" + "@react-stately/selection" "^3.20.6" + "@react-stately/tree" "^3.9.3" + "@react-types/button" "^3.14.1" + "@react-types/menu" "^3.10.5" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/meter@^3.4.22", "@react-aria/meter@^3.4.27": + version "3.4.27" + resolved "https://registry.yarnpkg.com/@react-aria/meter/-/meter-3.4.27.tgz#01cf9bbd12f05bd0515e048960690b017b0b9dd2" + integrity sha512-andOOdJkgRJF9vBi5VWRmFodK+GT+5X1lLeNUmb4qOX8/MVfX/RbK72LDeIhd7xC7rSCFHj3WvZ198rK4q0k3w== + dependencies: + "@react-aria/progress" "^3.4.27" + "@react-types/meter" "^3.4.13" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/numberfield@^3.11.13", "@react-aria/numberfield@^3.12.2": + version "3.12.2" + resolved "https://registry.yarnpkg.com/@react-aria/numberfield/-/numberfield-3.12.2.tgz#c219ecfba2076865e891cb2435c6bad558d6eabf" + integrity sha512-M2b+z0HIXiXpGAWOQkO2kpIjaLNUXJ5Q3/GMa3Fkr+B1piFX0VuOynYrtddKVrmXCe+r5t+XcGb0KS29uqv7nQ== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/spinbutton" "^3.6.19" + "@react-aria/textfield" "^3.18.2" + "@react-aria/utils" "^3.31.0" + "@react-stately/form" "^3.2.2" + "@react-stately/numberfield" "^3.10.2" + "@react-types/button" "^3.14.1" + "@react-types/numberfield" "^3.8.15" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/overlays@^3.27.0", "@react-aria/overlays@^3.30.0": + version "3.30.0" + resolved "https://registry.yarnpkg.com/@react-aria/overlays/-/overlays-3.30.0.tgz#e19f804c7fb9d99b25e33230cc3c155ed0b3cefb" + integrity sha512-UpjqSjYZx5FAhceWCRVsW6fX1sEwya1fQ/TKkL53FAlLFR8QKuoKqFlmiL43YUFTcGK3UdEOy3cWTleLQwdSmQ== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-aria/visually-hidden" "^3.8.28" + "@react-stately/overlays" "^3.6.20" + "@react-types/button" "^3.14.1" + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/progress@^3.4.22", "@react-aria/progress@^3.4.27": + version "3.4.27" + resolved "https://registry.yarnpkg.com/@react-aria/progress/-/progress-3.4.27.tgz#bdc968f133ddd33e5feaf2903d43aa34435dad51" + integrity sha512-0OA1shs1575g1zmO8+rWozdbTnxThFFhOfuoL1m7UV5Dley6FHpueoKB1ECv7B+Qm4dQt6DoEqLg7wsbbQDhmg== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/label" "^3.7.22" + "@react-aria/utils" "^3.31.0" + "@react-types/progress" "^3.5.16" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/radio@^3.11.2", "@react-aria/radio@^3.12.2": + version "3.12.2" + resolved "https://registry.yarnpkg.com/@react-aria/radio/-/radio-3.12.2.tgz#48ae0e9ba93e5c29e998fa3b64155a324a87f63e" + integrity sha512-I11f6I90neCh56rT/6ieAs3XyDKvEfbj/QmbU5cX3p+SJpRRPN0vxQi5D1hkh0uxDpeClxygSr31NmZsd4sqfg== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/form" "^3.1.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/utils" "^3.31.0" + "@react-stately/radio" "^3.11.2" + "@react-types/radio" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/searchfield@^3.8.3", "@react-aria/searchfield@^3.8.9": + version "3.8.9" + resolved "https://registry.yarnpkg.com/@react-aria/searchfield/-/searchfield-3.8.9.tgz#faa82c976bf3ef6c678bf9a2f9ae9bea9d4d3096" + integrity sha512-Yt2pj8Wb5/XsUr2T0DQqFv+DlFpzzWIWnNr9cJATUcWV/xw6ok7YFEg9+7EHtBmsCQxFFJtock1QfZzBw6qLtQ== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/textfield" "^3.18.2" + "@react-aria/utils" "^3.31.0" + "@react-stately/searchfield" "^3.5.16" + "@react-types/button" "^3.14.1" + "@react-types/searchfield" "^3.6.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/select@^3.15.4", "@react-aria/select@^3.17.0": + version "3.17.0" + resolved "https://registry.yarnpkg.com/@react-aria/select/-/select-3.17.0.tgz#d96933daca43939f4d59518f843c87a4f600426f" + integrity sha512-q5ZuyAn5jSOeI0Ys99951TaGcF4O7u1SSBVxPMwVVXOU8ZhToCNx+WG3n/JDYHEjqdo7sbsVRaPA7LkBzBGf5w== + dependencies: + "@react-aria/form" "^3.1.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/listbox" "^3.15.0" + "@react-aria/menu" "^3.19.3" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-aria/visually-hidden" "^3.8.28" + "@react-stately/select" "^3.8.0" + "@react-types/button" "^3.14.1" + "@react-types/select" "^3.11.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/selection@^3.24.0", "@react-aria/selection@^3.26.0": + version "3.26.0" + resolved "https://registry.yarnpkg.com/@react-aria/selection/-/selection-3.26.0.tgz#dc5906aa732b0dbd54d26dd6a5f1dc793055e29c" + integrity sha512-ZBH3EfWZ+RfhTj01dH8L17uT7iNbXWS8u77/fUpHgtrm0pwNVhx0TYVnLU1YpazQ/3WVpvWhmBB8sWwD1FlD/g== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/selection" "^3.20.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/separator@^3.4.13", "@react-aria/separator@^3.4.8": + version "3.4.13" + resolved "https://registry.yarnpkg.com/@react-aria/separator/-/separator-3.4.13.tgz#6eea332c68b67d1081f4d8c2af8198c6bc46bfb4" + integrity sha512-0NlcrdBfQbcjWEXdHl3+uSY1272n2ljT1gWL2RIf6aQsQWTZ0gz0rTgRHy0MTXN+y+tICItUERJT4vmTLtIzVg== + dependencies: + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/slider@^3.7.18", "@react-aria/slider@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@react-aria/slider/-/slider-3.8.2.tgz#a075205b06fa714733e3aabfdbc63d11f5c67be7" + integrity sha512-6KyUGaVzRE4xAz1LKHbNh1q5wzxe58pdTHFSnxNe6nk1SCoHw7NfI4h2s2m6LgJ0megFxsT0Ir8aHaFyyxmbgg== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/utils" "^3.31.0" + "@react-stately/slider" "^3.7.2" + "@react-types/shared" "^3.32.1" + "@react-types/slider" "^3.8.2" + "@swc/helpers" "^0.5.0" + +"@react-aria/spinbutton@^3.6.14", "@react-aria/spinbutton@^3.6.19": + version "3.6.19" + resolved "https://registry.yarnpkg.com/@react-aria/spinbutton/-/spinbutton-3.6.19.tgz#fd0253b95b88e9fb12ff406b722b4fd1e1c8c836" + integrity sha512-xOIXegDpts9t3RSHdIN0iYQpdts0FZ3LbpYJIYVvdEHo9OpDS+ElnDzCGtwZLguvZlwc5s1LAKuKopDUsAEMkw== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/utils" "^3.31.0" + "@react-types/button" "^3.14.1" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/ssr@^3.9.10", "@react-aria/ssr@^3.9.8": + version "3.9.10" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.10.tgz#7fdc09e811944ce0df1d7e713de1449abd7435e6" + integrity sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-aria/switch@^3.7.2", "@react-aria/switch@^3.7.8": + version "3.7.8" + resolved "https://registry.yarnpkg.com/@react-aria/switch/-/switch-3.7.8.tgz#e0a14f5eeda6017ae4d2b1cd236270d45c03e5ca" + integrity sha512-AfsUq1/YiuoprhcBUD9vDPyWaigAwctQNW1fMb8dROL+i/12B+Zekj8Ml+jbU69/kIVtfL0Jl7/0Bo9KK3X0xQ== + dependencies: + "@react-aria/toggle" "^3.12.2" + "@react-stately/toggle" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@react-types/switch" "^3.5.15" + "@swc/helpers" "^0.5.0" + +"@react-aria/table@^3.17.2", "@react-aria/table@^3.17.8": + version "3.17.8" + resolved "https://registry.yarnpkg.com/@react-aria/table/-/table-3.17.8.tgz#bf9c72cfe13775d6ad6934855f21456d73844ef0" + integrity sha512-bXiZoxTMbsqUJsYDhHPzKc3jw0HFJ/xMsJ49a0f7mp5r9zACxNLeIU0wJ4Uvx37dnYOHKzGliG+rj5l4sph7MA== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/grid" "^3.14.5" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/live-announcer" "^3.4.4" + "@react-aria/utils" "^3.31.0" + "@react-aria/visually-hidden" "^3.8.28" + "@react-stately/collections" "^3.12.8" + "@react-stately/flags" "^3.1.2" + "@react-stately/table" "^3.15.1" + "@react-types/checkbox" "^3.10.2" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@react-types/table" "^3.13.4" + "@swc/helpers" "^0.5.0" + +"@react-aria/tabs@^3.10.2", "@react-aria/tabs@^3.10.8": + version "3.10.8" + resolved "https://registry.yarnpkg.com/@react-aria/tabs/-/tabs-3.10.8.tgz#95c76badd8a9c9583449d0c765ab9289627847bc" + integrity sha512-sPPJyTyoAqsBh76JinBAxStOcbjZvyWFYKpJ9Uqw+XT0ObshAPPFSGeh8DiQemPs02RwJdrfARPMhyqiX8t59A== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/tabs" "^3.8.6" + "@react-types/shared" "^3.32.1" + "@react-types/tabs" "^3.3.19" + "@swc/helpers" "^0.5.0" + +"@react-aria/tag@^3.5.2", "@react-aria/tag@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-aria/tag/-/tag-3.7.2.tgz#5a655640deaf1705b8001abd636a7b96ae2250e9" + integrity sha512-JV679P5r4DftbqyNBRt7Nw9mP7dxaKPfikjyQuvUoEOa06wBLbM/hU9RJUPRvqK+Un6lgBDAmXD9NNf4N2xpdw== + dependencies: + "@react-aria/gridlist" "^3.14.1" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/list" "^3.13.1" + "@react-types/button" "^3.14.1" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/textfield@^3.17.2", "@react-aria/textfield@^3.18.2": + version "3.18.2" + resolved "https://registry.yarnpkg.com/@react-aria/textfield/-/textfield-3.18.2.tgz#d0198ac9833396f3b831e7e3c4cbe751979a4014" + integrity sha512-G+lM8VYSor6g9Yptc6hLZ6BF+0cq0pYol1z6wdQUQgJN8tg4HPtzq75lsZtlCSIznL3amgRAxJtd0dUrsAnvaQ== + dependencies: + "@react-aria/form" "^3.1.2" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/utils" "^3.31.0" + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@react-types/textfield" "^3.12.6" + "@swc/helpers" "^0.5.0" + +"@react-aria/toast@^3.0.2", "@react-aria/toast@^3.0.8": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@react-aria/toast/-/toast-3.0.8.tgz#50a751654a4f4917649a2a411f1e28418dc60dd1" + integrity sha512-rfJIms6AkMyQ7ZgKrMZgGfPwGcB/t1JoEwbc1PAmXcAvFI/hzF6YF7ZFDXiq38ucFsP9PnHmbXIzM9w4ccl18A== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/landmark" "^3.0.7" + "@react-aria/utils" "^3.31.0" + "@react-stately/toast" "^3.1.2" + "@react-types/button" "^3.14.1" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/toggle@^3.12.2": + version "3.12.2" + resolved "https://registry.yarnpkg.com/@react-aria/toggle/-/toggle-3.12.2.tgz#909c7c8b9bbeb2cc93a18297363eebb46354b0d4" + integrity sha512-g25XLYqJuJpt0/YoYz2Rab8ax+hBfbssllcEFh0v0jiwfk2gwTWfRU9KAZUvxIqbV8Nm8EBmrYychDpDcvW1kw== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/toggle" "^3.9.2" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/toolbar@3.0.0-beta.15": + version "3.0.0-beta.15" + resolved "https://registry.yarnpkg.com/@react-aria/toolbar/-/toolbar-3.0.0-beta.15.tgz#2b85e9a1f3e9185447e7164736cab7a859ed5f25" + integrity sha512-PNGpNIKIsCW8rxI9XXSADlLrSpikILJKKECyTRw9KwvXDRc44pezvdjGHCNinQcKsQoy5BtkK5cTSAyVqzzTXQ== + dependencies: + "@react-aria/focus" "^3.20.2" + "@react-aria/i18n" "^3.12.8" + "@react-aria/utils" "^3.28.2" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-aria/toolbar@3.0.0-beta.21": + version "3.0.0-beta.21" + resolved "https://registry.yarnpkg.com/@react-aria/toolbar/-/toolbar-3.0.0-beta.21.tgz#936929637fb89b1ba562aeeeeeaae6253a952bdd" + integrity sha512-yRCk/GD8g+BhdDgxd3I0a0c8Ni4Wyo6ERzfSoBkPkwQ4X2E2nkopmraM9D0fXw4UcIr4bnmvADzkHXtBN0XrBg== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/tooltip@^3.8.2", "@react-aria/tooltip@^3.8.8": + version "3.8.8" + resolved "https://registry.yarnpkg.com/@react-aria/tooltip/-/tooltip-3.8.8.tgz#a9320dd5edc953fbf7a24b9c30312408730e9743" + integrity sha512-CmHUqtXtFWmG4AHMEr9hIVex+oscK6xcM2V47gq9ijNInxe3M6UBu/dBdkgGP/jYv9N7tzCAjTR8nNIHQXwvWw== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/tooltip" "^3.5.8" + "@react-types/shared" "^3.32.1" + "@react-types/tooltip" "^3.4.21" + "@swc/helpers" "^0.5.0" + +"@react-aria/tree@^3.0.2", "@react-aria/tree@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@react-aria/tree/-/tree-3.1.4.tgz#d264355534c4af5203a6b6f3a659681504e31f00" + integrity sha512-6pbFeN0dAsCOrFGUKU39CNjft20zCAjLfMqfkRWisL+JkUHI2nq6odUJF5jJTsU1C+1951+3oFOmVxPX+K+akQ== + dependencies: + "@react-aria/gridlist" "^3.14.1" + "@react-aria/i18n" "^3.12.13" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/tree" "^3.9.3" + "@react-types/button" "^3.14.1" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/utils@^3.28.2", "@react-aria/utils@^3.31.0": + version "3.31.0" + resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.31.0.tgz#4710e35bf658234cf4b53eec9742f25e51637b12" + integrity sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-stately/flags" "^3.1.2" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-aria/virtualizer@^4.1.4": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@react-aria/virtualizer/-/virtualizer-4.1.10.tgz#af2e13a830d6c8e6ea31987229517285ce942d13" + integrity sha512-s0xOFh602ybTWuDrV/i6fV7Pz7vYghsY7F/RpYL/5IX9qCZ5C1FWFePpVktQAZghnd3ljH8hS8DULPeDfVLCrg== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/virtualizer" "^4.4.4" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/visually-hidden@^3.8.22", "@react-aria/visually-hidden@^3.8.28": + version "3.8.28" + resolved "https://registry.yarnpkg.com/@react-aria/visually-hidden/-/visually-hidden-3.8.28.tgz#61fc99c2d2662e7347abe25a421d138a3a81db46" + integrity sha512-KRRjbVVob2CeBidF24dzufMxBveEUtUu7IM+hpdZKB+gxVROoh4XRLPv9SFmaH89Z7D9To3QoykVZoWD0lan6Q== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-dnd/asap@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-4.0.1.tgz#5291850a6b58ce6f2da25352a64f1b0674871aab" + integrity sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg== + +"@react-dnd/invariant@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@react-dnd/invariant/-/invariant-2.0.0.tgz#09d2e81cd39e0e767d7da62df9325860f24e517e" + integrity sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw== + +"@react-dnd/shallowequal@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz#a3031eb54129f2c66b2753f8404266ec7bf67f0a" + integrity sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg== + +"@react-stately/autocomplete@3.0.0-beta.1": + version "3.0.0-beta.1" + resolved "https://registry.yarnpkg.com/@react-stately/autocomplete/-/autocomplete-3.0.0-beta.1.tgz#2e6ab2ea9702523bf6e9a8fb95ec4b79cb1993bc" + integrity sha512-ohs6QOtJouQ+Y1+zRKiCzv57QogSTRuOA1QfrnIS1YPwKO1EDQXSqFkq2htK5+bN9GCm94yo6r4iX++SZKmLXA== + dependencies: + "@react-stately/utils" "^3.10.6" + "@swc/helpers" "^0.5.0" + +"@react-stately/calendar@3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@react-stately/calendar/-/calendar-3.8.0.tgz#c8b051ef97d940eb4c1b4ac140a48b71868b628f" + integrity sha512-YAuJiR9EtVThX91gU2ay/6YgPe0LvZWEssu4BS0Atnwk5cAo32gvF5FMta9ztH1LIULdZFaypU/C1mvnayMf+Q== + dependencies: + "@internationalized/date" "^3.8.0" + "@react-stately/utils" "^3.10.6" + "@react-types/calendar" "^3.7.0" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-stately/calendar@^3.8.0", "@react-stately/calendar@^3.9.0": + version "3.9.0" + resolved "https://registry.yarnpkg.com/@react-stately/calendar/-/calendar-3.9.0.tgz#22da3b99692eabf53f94a58df7768d2135664c91" + integrity sha512-U5Nf2kx9gDhJRxdDUm5gjfyUlt/uUfOvM1vDW2UA62cA6+2k2cavMLc2wNlXOb/twFtl6p0joYKHG7T4xnEFkg== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-stately/utils" "^3.10.8" + "@react-types/calendar" "^3.8.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/checkbox@^3.6.13", "@react-stately/checkbox@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-stately/checkbox/-/checkbox-3.7.2.tgz#0a2293e7b97a366f94b7830d3deb2c0e9876c829" + integrity sha512-j1ycUVz5JmqhaL6mDZgDNZqBilOB8PBW096sDPFaTtuYreDx2HOd1igxiIvwlvPESZwsJP7FVM3mYnaoXtpKPA== + dependencies: + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/collections@^3.12.3", "@react-stately/collections@^3.12.8": + version "3.12.8" + resolved "https://registry.yarnpkg.com/@react-stately/collections/-/collections-3.12.8.tgz#f38692fb9c6384fb91d1c50052a40e595d3efa2c" + integrity sha512-AceJYLLXt1Y2XIcOPi6LEJSs4G/ubeYW3LqOCQbhfIgMaNqKfQMIfagDnPeJX9FVmPFSlgoCBxb1pTJW2vjCAQ== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/color@^3.8.4", "@react-stately/color@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-stately/color/-/color-3.9.2.tgz#87ac8461a01478208c302efa47582e872ff78c65" + integrity sha512-F+6Do8W3yu/4n7MpzZtbXwVukcLTFYYDIUtpoR+Jl52UmAr9Hf1CQgkyTI2azv1ZMzj1mVrTBhpBL0q27kFZig== + dependencies: + "@internationalized/number" "^3.6.5" + "@internationalized/string" "^3.2.7" + "@react-stately/form" "^3.2.2" + "@react-stately/numberfield" "^3.10.2" + "@react-stately/slider" "^3.7.2" + "@react-stately/utils" "^3.10.8" + "@react-types/color" "^3.1.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/combobox@^3.10.4", "@react-stately/combobox@^3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@react-stately/combobox/-/combobox-3.12.0.tgz#71e6c9a8ee2f75edc1d233df7b6d7a0b7aeb6fbe" + integrity sha512-A6q9R/7cEa/qoQsBkdslXWvD7ztNLLQ9AhBhVN9QvzrmrH5B4ymUwcTU8lWl22ykH7RRwfonLeLXJL4C+/L2oQ== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/form" "^3.2.2" + "@react-stately/list" "^3.13.1" + "@react-stately/overlays" "^3.6.20" + "@react-stately/utils" "^3.10.8" + "@react-types/combobox" "^3.13.9" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/data@^3.12.3", "@react-stately/data@^3.14.1": + version "3.14.1" + resolved "https://registry.yarnpkg.com/@react-stately/data/-/data-3.14.1.tgz#ba5550dee9d0d8ba10a4f6c763c3251631f73582" + integrity sha512-lDNc4gZ6kVZcrABeeQZPTTnP+1ykNylSvFzAC/Hq1fs8+s54xLRvoENWIyG+yK19N9TIGEoA0AOFG8PoAun43g== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/datepicker@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@react-stately/datepicker/-/datepicker-3.14.0.tgz#5f7e282d56e038ac0ef1b620fb9c1ff86253af57" + integrity sha512-JSkQfKW0+WpPQyOOeRPBLwXkVfpTUwgZJDnHBCud5kEuQiFFyeAIbL57RNXc4AX2pzY3piQa6OHnjDGTfqClxQ== + dependencies: + "@internationalized/date" "^3.8.0" + "@internationalized/string" "^3.2.6" + "@react-stately/form" "^3.1.3" + "@react-stately/overlays" "^3.6.15" + "@react-stately/utils" "^3.10.6" + "@react-types/datepicker" "^3.12.0" + "@react-types/shared" "^3.29.0" + "@swc/helpers" "^0.5.0" + +"@react-stately/datepicker@^3.14.0", "@react-stately/datepicker@^3.15.2": + version "3.15.2" + resolved "https://registry.yarnpkg.com/@react-stately/datepicker/-/datepicker-3.15.2.tgz#e873aecb5ec037b2da21b267c365c52443437dcb" + integrity sha512-S5GL+W37chvV8knv9v0JRv0L6hKo732qqabCCHXzOpYxkLIkV4f/y3cHdEzFWzpZ0O0Gkg7WgeYo160xOdBKYg== + dependencies: + "@internationalized/date" "^3.10.0" + "@internationalized/string" "^3.2.7" + "@react-stately/form" "^3.2.2" + "@react-stately/overlays" "^3.6.20" + "@react-stately/utils" "^3.10.8" + "@react-types/datepicker" "^3.13.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/disclosure@^3.0.3", "@react-stately/disclosure@^3.0.8": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@react-stately/disclosure/-/disclosure-3.0.8.tgz#ff6a3cc61993d25881cb8d6a82fcf829f139e02a" + integrity sha512-/Ce/Z76y85eSBZiemfU/uEyXkBBa1RdfLRaKD13rnfUV7/nS3ae1VtNlsXgmwQjWv2pmAiSuEKYMbZfVL7q/lQ== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/dnd@^3.5.3", "@react-stately/dnd@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@react-stately/dnd/-/dnd-3.7.1.tgz#23b2425553fc1cbc76821c96b30ecca1c9d16013" + integrity sha512-O1JBJ4HI1rVNKuoa5NXiC5FCrCEkr9KVBoKNlTZU8/cnQselhbEsUfMglAakO2EuwIaM1tIXoNF5J/N5P+6lTA== + dependencies: + "@react-stately/selection" "^3.20.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/flags@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-stately/flags/-/flags-3.1.2.tgz#5c8e5ae416d37d37e2e583d2fcb3a046293504f2" + integrity sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-stately/form@^3.1.3", "@react-stately/form@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@react-stately/form/-/form-3.2.2.tgz#c1ae1264a414dd5e3e8ae0f21baf4814588d8c53" + integrity sha512-soAheOd7oaTO6eNs6LXnfn0tTqvOoe3zN9FvtIhhrErKz9XPc5sUmh3QWwR45+zKbitOi1HOjfA/gifKhZcfWw== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/grid@^3.11.6": + version "3.11.6" + resolved "https://registry.yarnpkg.com/@react-stately/grid/-/grid-3.11.6.tgz#2993450ec5d0602e794f731fd49b3475f57e5547" + integrity sha512-vWPAkzpeTIsrurHfMubzMuqEw7vKzFhIJeEK5sEcLunyr1rlADwTzeWrHNbPMl66NAIAi70Dr1yNq+kahQyvMA== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/selection" "^3.20.6" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/layout@^4.2.2": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@react-stately/layout/-/layout-4.5.1.tgz#380b506409ef09bb032baf51055ef705e4320b02" + integrity sha512-Zk92HM6a8KFdyPzslhLCOmrrsvJ28+vFBisgiKMwVhe96cWlax1m9i4ktmO43xaUpSZkn06DRD/2k0d1x+Uwjw== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/table" "^3.15.1" + "@react-stately/virtualizer" "^4.4.4" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@react-types/table" "^3.13.4" + "@swc/helpers" "^0.5.0" + +"@react-stately/list@^3.12.1", "@react-stately/list@^3.13.1": + version "3.13.1" + resolved "https://registry.yarnpkg.com/@react-stately/list/-/list-3.13.1.tgz#4afd36a87c8fd991a4447d28cc76d51fffddb837" + integrity sha512-eHaoauh21twbcl0kkwULhVJ+CzYcy1jUjMikNVMHOQdhr4WIBdExf7PmSgKHKqsSPhpGg6IpTCY2dUX3RycjDg== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/selection" "^3.20.6" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/menu@^3.9.3", "@react-stately/menu@^3.9.8": + version "3.9.8" + resolved "https://registry.yarnpkg.com/@react-stately/menu/-/menu-3.9.8.tgz#5c2e781dadc3331bc5b3735fe30bf62616f9145f" + integrity sha512-bo0NOhofnTHLESiYfsSSw6gyXiPVJJ0UlN2igUXtJk5PmyhWjFzUzTzcnd7B028OB0si9w3LIWM3stqz5271Eg== + dependencies: + "@react-stately/overlays" "^3.6.20" + "@react-types/menu" "^3.10.5" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/numberfield@^3.10.2", "@react-stately/numberfield@^3.9.11": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@react-stately/numberfield/-/numberfield-3.10.2.tgz#aa1fcaec84cd441ea5e847dd3e9eca784045be21" + integrity sha512-jlKVFYaH3RX5KvQ7a+SAMQuPccZCzxLkeYkBE64u1Zvi7YhJ8hkTMHG/fmZMbk1rHlseE2wfBdk0Rlya3MvoNQ== + dependencies: + "@internationalized/number" "^3.6.5" + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/numberfield" "^3.8.15" + "@swc/helpers" "^0.5.0" + +"@react-stately/overlays@^3.6.15", "@react-stately/overlays@^3.6.20": + version "3.6.20" + resolved "https://registry.yarnpkg.com/@react-stately/overlays/-/overlays-3.6.20.tgz#e638ad0e073b6cf1d27f018aa41a4ce0fbae5f5b" + integrity sha512-YAIe+uI8GUXX8F/0Pzr53YeC5c/bjqbzDFlV8NKfdlCPa6+Jp4B/IlYVjIooBj9+94QvbQdjylegvYWK/iPwlg== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/overlays" "^3.9.2" + "@swc/helpers" "^0.5.0" + +"@react-stately/radio@^3.10.12", "@react-stately/radio@^3.11.2": + version "3.11.2" + resolved "https://registry.yarnpkg.com/@react-stately/radio/-/radio-3.11.2.tgz#a149fb9448dc258441662893f83a70e88e4d4aea" + integrity sha512-UM7L6AW+k8edhSBUEPZAqiWNRNadfOKK7BrCXyBiG79zTz0zPcXRR+N+gzkDn7EMSawDeyK1SHYUuoSltTactg== + dependencies: + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/radio" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/searchfield@^3.5.11", "@react-stately/searchfield@^3.5.16": + version "3.5.16" + resolved "https://registry.yarnpkg.com/@react-stately/searchfield/-/searchfield-3.5.16.tgz#3b768870d08fa2ef7747513d02d167717961d548" + integrity sha512-MRfqT1lZ24r94GuFNcGJXsfijZoWjSMySCT60T6NXtbOzVPuAF3K+pL70Rayq/EWLJjS2NPHND11VTs0VdcE0Q== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/searchfield" "^3.6.6" + "@swc/helpers" "^0.5.0" + +"@react-stately/select@^3.6.12", "@react-stately/select@^3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@react-stately/select/-/select-3.8.0.tgz#ccb1b7d6d0f40b166444f3df27273892854ff23e" + integrity sha512-A721nlt0DSCDit0wKvhcrXFTG5Vv1qkEVkeKvobmETZy6piKvwh0aaN8iQno5AFuZaj1iOZeNjZ/20TsDJR/4A== + dependencies: + "@react-stately/form" "^3.2.2" + "@react-stately/list" "^3.13.1" + "@react-stately/overlays" "^3.6.20" + "@react-stately/utils" "^3.10.8" + "@react-types/select" "^3.11.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/selection@^3.20.1", "@react-stately/selection@^3.20.6": + version "3.20.6" + resolved "https://registry.yarnpkg.com/@react-stately/selection/-/selection-3.20.6.tgz#17d4d4553403de6ab690172a8d36e0423a5173fb" + integrity sha512-a0bjuP2pJYPKEiedz2Us1W1aSz0iHRuyeQEdBOyL6Z6VUa6hIMq9H60kvseir2T85cOa4QggizuRV7mcO6bU5w== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/slider@^3.6.3", "@react-stately/slider@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-stately/slider/-/slider-3.7.2.tgz#9dfe6f7e74397f717b1623bc06ba8e375510d056" + integrity sha512-EVBHUdUYwj++XqAEiQg2fGi8Reccznba0uyQ3gPejF0pAc390Q/J5aqiTEDfiCM7uJ6WHxTM6lcCqHQBISk2dQ== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@react-types/slider" "^3.8.2" + "@swc/helpers" "^0.5.0" + +"@react-stately/table@^3.14.1", "@react-stately/table@^3.15.1": + version "3.15.1" + resolved "https://registry.yarnpkg.com/@react-stately/table/-/table-3.15.1.tgz#3a2f5ca0788cea200c4c96858604fb4c0139f8b0" + integrity sha512-MhMAgE/LgAzHcAn1P3p/nQErzJ6DiixSJ1AOt2JlnAKEb5YJg4ATKWCb2IjBLwywt9ZCzfm3KMUzkctZqAoxwA== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/flags" "^3.1.2" + "@react-stately/grid" "^3.11.6" + "@react-stately/selection" "^3.20.6" + "@react-stately/utils" "^3.10.8" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@react-types/table" "^3.13.4" + "@swc/helpers" "^0.5.0" + +"@react-stately/tabs@^3.8.1", "@react-stately/tabs@^3.8.6": + version "3.8.6" + resolved "https://registry.yarnpkg.com/@react-stately/tabs/-/tabs-3.8.6.tgz#c71e3ed2462d89ad9c06fb78c69b2069625c68fd" + integrity sha512-9RYxmgjVIxUpIsGKPIF7uRoHWOEz8muwaYiStCVeyiYBPmarvZoIYtTXcwSMN/vEs7heVN5uGCL6/bfdY4+WiA== + dependencies: + "@react-stately/list" "^3.13.1" + "@react-types/shared" "^3.32.1" + "@react-types/tabs" "^3.3.19" + "@swc/helpers" "^0.5.0" + +"@react-stately/toast@^3.1.0", "@react-stately/toast@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-stately/toast/-/toast-3.1.2.tgz#0502040b6bd57479eaba1bca2f4c66e9e957e55a" + integrity sha512-HiInm7bck32khFBHZThTQaAF6e6/qm57F4mYRWdTq8IVeGDzpkbUYibnLxRhk0UZ5ybc6me+nqqPkG/lVmM42Q== + dependencies: + "@swc/helpers" "^0.5.0" + use-sync-external-store "^1.4.0" + +"@react-stately/toggle@^3.8.3", "@react-stately/toggle@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-stately/toggle/-/toggle-3.9.2.tgz#8a50def68efdcefa268a870deda8bb65e5f054a8" + integrity sha512-dOxs9wrVXHUmA7lc8l+N9NbTJMAaXcYsnNGsMwfXIXQ3rdq+IjWGNYJ52UmNQyRYFcg0jrzRrU16TyGbNjOdNQ== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/tooltip@^3.5.3", "@react-stately/tooltip@^3.5.8": + version "3.5.8" + resolved "https://registry.yarnpkg.com/@react-stately/tooltip/-/tooltip-3.5.8.tgz#c4a329c63294e8ccae3d9ee7853d40c2fb93ce73" + integrity sha512-gkcUx2ROhCiGNAYd2BaTejakXUUNLPnnoJ5+V/mN480pN+OrO8/2V9pqb/IQmpqxLsso93zkM3A4wFHHLBBmPQ== + dependencies: + "@react-stately/overlays" "^3.6.20" + "@react-types/tooltip" "^3.4.21" + "@swc/helpers" "^0.5.0" + +"@react-stately/tree@^3.8.9", "@react-stately/tree@^3.9.3": + version "3.9.3" + resolved "https://registry.yarnpkg.com/@react-stately/tree/-/tree-3.9.3.tgz#398de3406d2a06477bb0af2bdb2a0021265eeade" + integrity sha512-ZngG79nLFxE/GYmpwX6E/Rma2MMkzdoJPRI3iWk3dgqnGMMzpPnUp/cvjDsU3UHF7xDVusC5BT6pjWN0uxCIFQ== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/selection" "^3.20.6" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/utils@^3.10.6", "@react-stately/utils@^3.10.8": + version "3.10.8" + resolved "https://registry.yarnpkg.com/@react-stately/utils/-/utils-3.10.8.tgz#fdb9d172f7bbc2d083e69190f5ef0edfa4b4392f" + integrity sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-stately/virtualizer@^4.3.2", "@react-stately/virtualizer@^4.4.4": + version "4.4.4" + resolved "https://registry.yarnpkg.com/@react-stately/virtualizer/-/virtualizer-4.4.4.tgz#b2a48bf6bf22f59532d9c6d71d010845b0088ed1" + integrity sha512-ri8giqXSZOrznZDCCOE4U36wSkOhy+hrFK7yo/YVcpxTqqp3d3eisfKMqbDsgqBW+XTHycTU/xeAf0u9NqrfpQ== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-types/autocomplete@3.0.0-alpha.30": + version "3.0.0-alpha.30" + resolved "https://registry.yarnpkg.com/@react-types/autocomplete/-/autocomplete-3.0.0-alpha.30.tgz#c4672644f762d112557c54e78fddf1f8f9ae4146" + integrity sha512-9neGygI+stJqiEFHzoc1jMySj6lOc4MUmBmu0uGn2zdOG2zxaAZSjh1pd9AJkHNyZ4j/n5rVXMo+v3RNkUntNw== + dependencies: + "@react-types/combobox" "^3.13.4" + "@react-types/searchfield" "^3.6.1" + "@react-types/shared" "^3.29.0" + +"@react-types/breadcrumbs@^3.7.17": + version "3.7.17" + resolved "https://registry.yarnpkg.com/@react-types/breadcrumbs/-/breadcrumbs-3.7.17.tgz#e584352cc4f79e638e20774af04f28064cd9b66b" + integrity sha512-IhvVTcfli5o/UDlGACXxjlor2afGlMQA8pNR3faH0bBUay1Fmm3IWktVw9Xwmk+KraV2RTAg9e+E6p8DOQZfiw== + dependencies: + "@react-types/link" "^3.6.5" + "@react-types/shared" "^3.32.1" + +"@react-types/button@^3.12.0", "@react-types/button@^3.14.1": + version "3.14.1" + resolved "https://registry.yarnpkg.com/@react-types/button/-/button-3.14.1.tgz#41c25f7c7dd1b31a359a6af9cbec5bed5dbb5aa1" + integrity sha512-D8C4IEwKB7zEtiWYVJ3WE/5HDcWlze9mLWQ5hfsBfpePyWCgO3bT/+wjb/7pJvcAocrkXo90QrMm85LcpBtrpg== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/calendar@^3.7.0", "@react-types/calendar@^3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@react-types/calendar/-/calendar-3.8.0.tgz#51dad3445586f1c22886c35499cfcc872462a30f" + integrity sha512-ZDZgfZgbz1ydWOFs1mH7QFfX3ioJrmb3Y/lkoubQE0HWXLZzyYNvhhKyFJRS1QJ40IofLSBHriwbQb/tsUnGlw== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-types/shared" "^3.32.1" + +"@react-types/checkbox@^3.10.2": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@react-types/checkbox/-/checkbox-3.10.2.tgz#0190c9690e3649348a4d7045b168cbda657ce9de" + integrity sha512-ktPkl6ZfIdGS1tIaGSU/2S5Agf2NvXI9qAgtdMDNva0oLyAZ4RLQb6WecPvofw1J7YKXu0VA5Mu7nlX+FM2weQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/color@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-types/color/-/color-3.1.2.tgz#06a0e81b463f3a8d4553e7cd535b2881d721e231" + integrity sha512-NP0TAY3j4tlMztOp/bBfMlPwC9AQKTjSiTFmc2oQNkx5M4sl3QpPqFPosdt7jZ8M4nItvfCWZrlZGjST4SB83A== + dependencies: + "@react-types/shared" "^3.32.1" + "@react-types/slider" "^3.8.2" + +"@react-types/combobox@^3.13.4", "@react-types/combobox@^3.13.9": + version "3.13.9" + resolved "https://registry.yarnpkg.com/@react-types/combobox/-/combobox-3.13.9.tgz#58bc5c39ca1d7bdbb4beebf79d2ba11b337e927f" + integrity sha512-G6GmLbzVkLW6VScxPAr/RtliEyPhBClfYaIllK1IZv+Z42SVnOpKzhnoe79BpmiFqy1AaC3+LjZX783mrsHCwA== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/datepicker@^3.12.0", "@react-types/datepicker@^3.13.2": + version "3.13.2" + resolved "https://registry.yarnpkg.com/@react-types/datepicker/-/datepicker-3.13.2.tgz#775e43b6edcb8d3d5968e0a35cfacd14be3c847c" + integrity sha512-+M6UZxJnejYY8kz0spbY/hP08QJ5rsZ3aNarRQQHc48xV2oelFLX5MhAqizfLEsvyfb0JYrhWoh4z1xZtAmYCg== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-types/calendar" "^3.8.0" + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@react-types/dialog@^3.5.17", "@react-types/dialog@^3.5.22": + version "3.5.22" + resolved "https://registry.yarnpkg.com/@react-types/dialog/-/dialog-3.5.22.tgz#ed772c303042c6ee5e8a9bc9e58b5b9d08ed634b" + integrity sha512-smSvzOcqKE196rWk0oqJDnz+ox5JM5+OT0PmmJXiUD4q7P5g32O6W5Bg7hMIFUI9clBtngo8kLaX2iMg+GqAzg== + dependencies: + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@react-types/form@^3.7.11": + version "3.7.16" + resolved "https://registry.yarnpkg.com/@react-types/form/-/form-3.7.16.tgz#4285880a03db2b9f664246b6f2f2421ef18a49da" + integrity sha512-Sb7KJoWEaQ/e4XIY+xRbjKvbP1luome98ZXevpD+zVSyGjEcfIroebizP6K1yMHCWP/043xH6GUkgEqWPoVGjg== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/grid@^3.3.1", "@react-types/grid@^3.3.6": + version "3.3.6" + resolved "https://registry.yarnpkg.com/@react-types/grid/-/grid-3.3.6.tgz#9fc60f5baa8a1668bb2257a981dd514dd64706c3" + integrity sha512-vIZJlYTii2n1We9nAugXwM2wpcpsC6JigJFBd6vGhStRdRWRoU4yv1Gc98Usbx0FQ/J7GLVIgeG8+1VMTKBdxw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/link@^3.6.5": + version "3.6.5" + resolved "https://registry.yarnpkg.com/@react-types/link/-/link-3.6.5.tgz#28cf2b90f69e83af7ff507021eec0449f148eb45" + integrity sha512-+I2s3XWBEvLrzts0GnNeA84mUkwo+a7kLUWoaJkW0TOBDG7my95HFYxF9WnqKye7NgpOkCqz4s3oW96xPdIniQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/listbox@^3.7.4": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@react-types/listbox/-/listbox-3.7.4.tgz#712329de62c0fddf44c062bb18c51135309c9fe8" + integrity sha512-p4YEpTl/VQGrqVE8GIfqTS5LkT5jtjDTbVeZgrkPnX/fiPhsfbTPiZ6g0FNap4+aOGJFGEEZUv2q4vx+rCORww== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/menu@^3.10.5": + version "3.10.5" + resolved "https://registry.yarnpkg.com/@react-types/menu/-/menu-3.10.5.tgz#0e3a66aab3c636dc3ef965529640bb678b13a431" + integrity sha512-HBTrKll2hm0VKJNM4ubIv1L9MNo8JuOnm2G3M+wXvb6EYIyDNxxJkhjsqsGpUXJdAOSkacHBDcNh2HsZABNX4A== + dependencies: + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@react-types/meter@^3.4.13": + version "3.4.13" + resolved "https://registry.yarnpkg.com/@react-types/meter/-/meter-3.4.13.tgz#ddd54e1d56a9af79646d832a3cf4a8979e473ead" + integrity sha512-EiarfbpHcvmeyXvXcr6XLaHkNHuGc4g7fBVEiDPwssFJKKfbUzqnnknDxPjyspqUVRcXC08CokS98J1jYobqDg== + dependencies: + "@react-types/progress" "^3.5.16" + +"@react-types/numberfield@^3.8.15": + version "3.8.15" + resolved "https://registry.yarnpkg.com/@react-types/numberfield/-/numberfield-3.8.15.tgz#0fcd77217bae5d7a2bf35d41c7eb61d8ae52bc03" + integrity sha512-97r92D23GKCOjGIGMeW9nt+/KlfM3GeWH39Czcmd2/D5y3k6z4j0avbsfx2OttCtJszrnENjw3GraYGYI2KosQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/overlays@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-types/overlays/-/overlays-3.9.2.tgz#721dc248afcb42db988391037a6386bb61556cd4" + integrity sha512-Q0cRPcBGzNGmC8dBuHyoPR7N3057KTS5g+vZfQ53k8WwmilXBtemFJPLsogJbspuewQ/QJ3o2HYsp2pne7/iNw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/progress@^3.5.16": + version "3.5.16" + resolved "https://registry.yarnpkg.com/@react-types/progress/-/progress-3.5.16.tgz#f40e1b674e630276d6412297a92eb0dd3761d426" + integrity sha512-I9tSdCFfvQ7gHJtm90VAKgwdTWXQgVNvLRStEc0z9h+bXBxdvZb+QuiRPERChwFQ9VkK4p4rDqaFo69nDqWkpw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/radio@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-types/radio/-/radio-3.9.2.tgz#c6ac396b49cc03334e4bb63a96f366effce3a615" + integrity sha512-3UcJXu37JrTkRyP4GJPDBU7NmDTInrEdOe+bVzA1j4EegzdkJmLBkLg5cLDAbpiEHB+xIsvbJdx6dxeMuc+H3g== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/searchfield@^3.6.1", "@react-types/searchfield@^3.6.6": + version "3.6.6" + resolved "https://registry.yarnpkg.com/@react-types/searchfield/-/searchfield-3.6.6.tgz#fd41bd78246789ac4284462abe222b6f85d191b2" + integrity sha512-cl3itr/fk7wbIQc2Gz5Ie8aVeUmPjVX/mRGS5/EXlmzycAKNYTvqf2mlxwObLndtLISmt7IgNjRRhbUUDI8Ang== + dependencies: + "@react-types/shared" "^3.32.1" + "@react-types/textfield" "^3.12.6" + +"@react-types/select@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@react-types/select/-/select-3.11.0.tgz#808aec480f0cc20075953af9717ca38d1eb15b8d" + integrity sha512-SzIsMFVPCbXE1Z1TLfpdfiwJ1xnIkcL1/CjGilmUKkNk5uT7rYX1xCJqWCjXI0vAU1xM4Qn+T3n8de4fw6HRBg== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/shared@^3.29.0", "@react-types/shared@^3.32.1": + version "3.32.1" + resolved "https://registry.yarnpkg.com/@react-types/shared/-/shared-3.32.1.tgz#abfeb839d65d0abe923576f34ac08342c25dfa55" + integrity sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w== + +"@react-types/slider@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@react-types/slider/-/slider-3.8.2.tgz#37e02c42514aca842954c715082d1ae06a661ee4" + integrity sha512-MQYZP76OEOYe7/yA2To+Dl0LNb0cKKnvh5JtvNvDnAvEprn1RuLiay8Oi/rTtXmc2KmBa4VdTcsXsmkbbkeN2Q== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/switch@^3.5.15": + version "3.5.15" + resolved "https://registry.yarnpkg.com/@react-types/switch/-/switch-3.5.15.tgz#43806d6e7034d1d07e20c89ec9618e607fef9e62" + integrity sha512-r/ouGWQmIeHyYSP1e5luET+oiR7N7cLrAlWsrAfYRWHxqXOSNQloQnZJ3PLHrKFT02fsrQhx2rHaK2LfKeyN3A== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/table@^3.12.0", "@react-types/table@^3.13.4": + version "3.13.4" + resolved "https://registry.yarnpkg.com/@react-types/table/-/table-3.13.4.tgz#c3d5952d4bd2a04992255850538856829b12c99a" + integrity sha512-I/DYiZQl6aNbMmjk90J9SOhkzVDZvyA3Vn3wMWCiajkMNjvubFhTfda5DDf2SgFP5l0Yh6TGGH5XumRv9LqL5Q== + dependencies: + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + +"@react-types/tabs@^3.3.19": + version "3.3.19" + resolved "https://registry.yarnpkg.com/@react-types/tabs/-/tabs-3.3.19.tgz#344a22bd15400b738aebc26918cf96dacde1ffef" + integrity sha512-fE+qI43yR5pAMpeqPxGqQq9jDHXEPqXskuxNHERMW0PYMdPyem2Cw6goc5F4qeZO3Hf6uPZgHkvJz2OAq7TbBw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/textfield@^3.12.6": + version "3.12.6" + resolved "https://registry.yarnpkg.com/@react-types/textfield/-/textfield-3.12.6.tgz#0f90a4108c8d75e7c2c26753e760cd580339be12" + integrity sha512-hpEVKE+M3uUkTjw2WrX1NrH/B3rqDJFUa+ViNK2eVranLY4ZwFqbqaYXSzHupOF3ecSjJJv2C103JrwFvx6TPQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/tooltip@^3.4.21": + version "3.4.21" + resolved "https://registry.yarnpkg.com/@react-types/tooltip/-/tooltip-3.4.21.tgz#63596cf87d7166499656bc15f212c75c9ffa8991" + integrity sha512-ugGHOZU6WbOdeTdbjnaEc+Ms7/WhsUCg+T3PCOIeOT9FG02Ce189yJ/+hd7oqL/tVwIhEMYJIqSCgSELFox+QA== + dependencies: + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@rolldown/pluginutils@1.0.0-beta.47": + version "1.0.0-beta.47" + resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz#c282c4a8c39f3d6d2f1086aae09a34e6241f7a50" + integrity sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw== + +"@rollup/pluginutils@^5.1.4": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.3.0.tgz#57ba1b0cbda8e7a3c597a4853c807b156e21a7b4" + integrity sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^4.0.2" + +"@rollup/rollup-android-arm-eabi@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz#7e478b66180c5330429dd161bf84dad66b59c8eb" + integrity sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w== + +"@rollup/rollup-android-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz#2b025510c53a5e3962d3edade91fba9368c9d71c" + integrity sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w== + +"@rollup/rollup-darwin-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz#3577c38af68ccf34c03e84f476bfd526abca10a0" + integrity sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA== + +"@rollup/rollup-darwin-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz#2bf5f2520a1f3b551723d274b9669ba5b75ed69c" + integrity sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ== + +"@rollup/rollup-freebsd-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz#4bb9cc80252564c158efc0710153c71633f1927c" + integrity sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w== + +"@rollup/rollup-freebsd-x64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz#2301289094d49415a380cf942219ae9d8b127440" + integrity sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q== + +"@rollup/rollup-linux-arm-gnueabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz#1d03d776f2065e09fc141df7d143476e94acca88" + integrity sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw== + +"@rollup/rollup-linux-arm-musleabihf@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz#8623de0e040b2fd52a541c602688228f51f96701" + integrity sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg== + +"@rollup/rollup-linux-arm64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz#ce2d1999bc166277935dde0301cde3dd0417fb6e" + integrity sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w== + +"@rollup/rollup-linux-arm64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz#88c2523778444da952651a2219026416564a4899" + integrity sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A== + +"@rollup/rollup-linux-loong64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz#578ca2220a200ac4226c536c10c8cc6e4f276714" + integrity sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g== + +"@rollup/rollup-linux-ppc64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz#aa338d3effd4168a20a5023834a74ba2c3081293" + integrity sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw== + +"@rollup/rollup-linux-riscv64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz#16ba582f9f6cff58119aa242782209b1557a1508" + integrity sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g== + +"@rollup/rollup-linux-riscv64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz#e404a77ebd6378483888b8064c703adb011340ab" + integrity sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A== + +"@rollup/rollup-linux-s390x-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz#92ad52d306227c56bec43d96ad2164495437ffe6" + integrity sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg== + +"@rollup/rollup-linux-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz#fd0dea3bb9aa07e7083579f25e1c2285a46cb9fa" + integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== + +"@rollup/rollup-linux-x64-musl@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz#37a3efb09f18d555f8afc490e1f0444885de8951" + integrity sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q== + +"@rollup/rollup-openharmony-arm64@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz#c489bec9f4f8320d42c9b324cca220c90091c1f7" + integrity sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw== + +"@rollup/rollup-win32-arm64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz#152832b5f79dc22d1606fac3db946283601b7080" + integrity sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw== + +"@rollup/rollup-win32-ia32-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz#54d91b2bb3bf3e9f30d32b72065a4e52b3a172a5" + integrity sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA== + +"@rollup/rollup-win32-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz#df9df03e61a003873efec8decd2034e7f135c71e" + integrity sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg== + +"@rollup/rollup-win32-x64-msvc@4.53.3": + version "4.53.3" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz#38ae84f4c04226c1d56a3b17296ef1e0460ecdfe" + integrity sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ== + +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== + +"@rushstack/eslint-patch@^1.10.3": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz#8184bcb37791e6d3c3c13a9bfbe4af263f66665f" + integrity sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw== + +"@rushstack/node-core-library@5.18.0": + version "5.18.0" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-5.18.0.tgz#b184c9f375fba45bca69cba60e7938d495d11c53" + integrity sha512-XDebtBdw5S3SuZIt+Ra2NieT8kQ3D2Ow1HxhDQ/2soinswnOu9e7S69VSwTOLlQnx5mpWbONu+5JJjDxMAb6Fw== + dependencies: + ajv "~8.13.0" + ajv-draft-04 "~1.0.0" + ajv-formats "~3.0.1" + fs-extra "~11.3.0" + import-lazy "~4.0.0" + jju "~1.4.0" + resolve "~1.22.1" + semver "~7.5.4" + +"@rushstack/problem-matcher@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@rushstack/problem-matcher/-/problem-matcher-0.1.1.tgz#db9303ef3c47010c8aba5841e8c9511e091159df" + integrity sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA== + +"@rushstack/rig-package@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@rushstack/rig-package/-/rig-package-0.6.0.tgz#c80f93fe2c0d9d4977fc925ed9ce9decb75047a5" + integrity sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw== + dependencies: + resolve "~1.22.1" + strip-json-comments "~3.1.1" + +"@rushstack/terminal@0.19.3": + version "0.19.3" + resolved "https://registry.yarnpkg.com/@rushstack/terminal/-/terminal-0.19.3.tgz#d09ba5a0c2cb5358eba443ea3819936b654c16d9" + integrity sha512-0P8G18gK9STyO+CNBvkKPnWGMxESxecTYqOcikHOVIHXa9uAuTK+Fw8TJq2Gng1w7W6wTC9uPX6hGNvrMll2wA== + dependencies: + "@rushstack/node-core-library" "5.18.0" + "@rushstack/problem-matcher" "0.1.1" + supports-color "~8.1.1" + +"@rushstack/ts-command-line@5.1.3": + version "5.1.3" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-5.1.3.tgz#c3e4e3d14b208f3d60166be4e7c9f9c9cfa0a85e" + integrity sha512-Kdv0k/BnnxIYFlMVC1IxrIS0oGQd4T4b7vKfx52Y2+wk2WZSDFIvedr7JrhenzSlm3ou5KwtoTGTGd5nbODRug== + dependencies: + "@rushstack/terminal" "0.19.3" + "@types/argparse" "1.0.38" + argparse "~1.0.9" + string-argv "~0.3.1" + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@swc/core-darwin-arm64@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.2.tgz#591fde48757f9c66f050eb82353def199c9967af" + integrity sha512-Ghyz4RJv4zyXzrUC1B2MLQBbppIB5c4jMZJybX2ebdEQAvryEKp3gq1kBksCNsatKGmEgXul88SETU19sMWcrw== + +"@swc/core-darwin-x64@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.15.2.tgz#f0c229fd21b0ef658cf50adb8b9a5f8c1919d2ec" + integrity sha512-7n/PGJOcL2QoptzL42L5xFFfXY5rFxLHnuz1foU+4ruUTG8x2IebGhtwVTpaDN8ShEv2UZObBlT1rrXTba15Zw== + +"@swc/core-linux-arm-gnueabihf@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.2.tgz#ab6d8535ab0294fb743044665c1c17330ccc2181" + integrity sha512-ZUQVCfRJ9wimuxkStRSlLwqX4TEDmv6/J+E6FicGkQ6ssLMWoKDy0cAo93HiWt/TWEee5vFhFaSQYzCuBEGO6A== + +"@swc/core-linux-arm64-gnu@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.2.tgz#c5db7bbba6af3bd93fd79b74850cf2fe04f1c074" + integrity sha512-GZh3pYBmfnpQ+JIg+TqLuz+pM+Mjsk5VOzi8nwKn/m+GvQBsxD5ectRtxuWUxMGNG8h0lMy4SnHRqdK3/iJl7A== + +"@swc/core-linux-arm64-musl@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.2.tgz#31cd61e6c83595248fda70a70e596f0a7f6cdf97" + integrity sha512-5av6VYZZeneiYIodwzGMlnyVakpuYZryGzFIbgu1XP8wVylZxduEzup4eP8atiMDFmIm+s4wn8GySJmYqeJC0A== + +"@swc/core-linux-x64-gnu@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.2.tgz#c857e95635fa2beaf6d3ecb9b1bd97ade5cda43a" + integrity sha512-1nO/UfdCLuT/uE/7oB3EZgTeZDCIa6nL72cFEpdegnqpJVNDI6Qb8U4g/4lfVPkmHq2lvxQ0L+n+JdgaZLhrRA== + +"@swc/core-linux-x64-musl@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.2.tgz#afa817865271f24502a0805cfab70ba553ade146" + integrity sha512-Ksfrb0Tx310kr+TLiUOvB/I80lyZ3lSOp6cM18zmNRT/92NB4mW8oX2Jo7K4eVEI2JWyaQUAFubDSha2Q+439A== + +"@swc/core-win32-arm64-msvc@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.2.tgz#5696added38837b6b3f442d63989ef4fcaa2d3de" + integrity sha512-IzUb5RlMUY0r1A9IuJrQ7Tbts1wWb73/zXVXT8VhewbHGoNlBKE0qUhKMED6Tv4wDF+pmbtUJmKXDthytAvLmg== + +"@swc/core-win32-ia32-msvc@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.2.tgz#3e42427998d49b54c55d49752b410309c7d02357" + integrity sha512-kCATEzuY2LP9AlbU2uScjcVhgnCAkRdu62vbce17Ro5kxEHxYWcugkveyBRS3AqZGtwAKYbMAuNloer9LS/hpw== + +"@swc/core-win32-x64-msvc@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.2.tgz#fa6505e20a3753b6884b35353d1614a03c54df7f" + integrity sha512-iJaHeYCF4jTn7OEKSa3KRiuVFIVYts8jYjNmCdyz1u5g8HRyTDISD76r8+ljEOgm36oviRQvcXaw6LFp1m0yyA== + +"@swc/core@^1.13.5": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.15.2.tgz#94c783f959fdc12c9d811b8345d791e9592a628a" + integrity sha512-OQm+yJdXxvSjqGeaWhP6Ia264ogifwAO7Q12uTDVYj/Ks4jBTI4JknlcjDRAXtRhqbWsfbZyK/5RtuIPyptk3w== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.25" + optionalDependencies: + "@swc/core-darwin-arm64" "1.15.2" + "@swc/core-darwin-x64" "1.15.2" + "@swc/core-linux-arm-gnueabihf" "1.15.2" + "@swc/core-linux-arm64-gnu" "1.15.2" + "@swc/core-linux-arm64-musl" "1.15.2" + "@swc/core-linux-x64-gnu" "1.15.2" + "@swc/core-linux-x64-musl" "1.15.2" + "@swc/core-win32-arm64-msvc" "1.15.2" + "@swc/core-win32-ia32-msvc" "1.15.2" + "@swc/core-win32-x64-msvc" "1.15.2" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.15.tgz#79efab344c5819ecf83a43f3f9f811fc84b516d7" + integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g== + dependencies: + tslib "^2.8.0" + +"@swc/helpers@^0.5.0": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" + integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A== + dependencies: + tslib "^2.8.0" + +"@swc/types@^0.1.25": + version "0.1.25" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.25.tgz#b517b2a60feb37dd933e542d93093719e4cf1078" + integrity sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g== + dependencies: + "@swc/counter" "^0.1.3" + +"@tanstack/eslint-plugin-query@5.66.1": + version "5.66.1" + resolved "https://registry.yarnpkg.com/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.66.1.tgz#9951e4d3633ca6248196742cad437b4d7c760cd7" + integrity sha512-pYMVTGgJ7yPk9Rm6UWEmbY6TX0EmMmxJqYkthgeDCwEznToy2m+W928nUODFirtZBZlhBsqHy33LO0kyTlgf0w== + dependencies: + "@typescript-eslint/utils" "^8.18.1" + +"@tanstack/eslint-plugin-query@5.91.2": + version "5.91.2" + resolved "https://registry.yarnpkg.com/@tanstack/eslint-plugin-query/-/eslint-plugin-query-5.91.2.tgz#dc47394f9d08d78ce811c405b9620a259e4368cb" + integrity sha512-UPeWKl/Acu1IuuHJlsN+eITUHqAaa9/04geHHPedY8siVarSaWprY0SVMKrkpKfk5ehRT7+/MZ5QwWuEtkWrFw== + dependencies: + "@typescript-eslint/utils" "^8.44.1" + +"@tanstack/query-core@5.90.10": + version "5.90.10" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.90.10.tgz#2704b038277fb41e631f356e7428951b5354ed13" + integrity sha512-EhZVFu9rl7GfRNuJLJ3Y7wtbTnENsvzp+YpcAV7kCYiXni1v8qZh++lpw4ch4rrwC0u/EZRnBHIehzCGzwXDSQ== + +"@tanstack/query-devtools@5.65.0": + version "5.65.0" + resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.65.0.tgz#37da5e911543b4f6d98b9a04369eab0de6044ba1" + integrity sha512-g5y7zc07U9D3esMdqUfTEVu9kMHoIaVBsD0+M3LPdAdD710RpTcLiNvJY1JkYXqkq9+NV+CQoemVNpQPBXVsJg== + +"@tanstack/react-query-devtools@5.66.9": + version "5.66.9" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.66.9.tgz#5cb69b874682289e5014bcf9b6460a2d35df129f" + integrity sha512-70G6AR35he53SYUcUK6EdqNR18zejCv1rM6900gjZP408EAex56YLwVSeijzk9lWeU2J42G9Fjh0i1WngUTsgw== + dependencies: + "@tanstack/query-devtools" "5.65.0" + +"@tanstack/react-query@5.90.10": + version "5.90.10" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.90.10.tgz#dc2d4acbe1c06b708ccaeed43a26ad56bc5d1718" + integrity sha512-BKLss9Y8PQ9IUjPYQiv3/Zmlx92uxffUOX8ZZNoQlCIZBJPT5M+GOMQj7xislvVQ6l1BstBjcX0XB/aHfFYVNw== + dependencies: + "@tanstack/query-core" "5.90.10" + +"@tanstack/react-table@8.21.3": + version "8.21.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.21.3.tgz#2c38c747a5731c1a07174fda764b9c2b1fb5e91b" + integrity sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww== + dependencies: + "@tanstack/table-core" "8.21.3" + +"@tanstack/table-core@8.21.3": + version "8.21.3" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.21.3.tgz#2977727d8fc8dfa079112d9f4d4c019110f1732c" + integrity sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg== + +"@tsconfig/node10@^1.0.7": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.12.tgz#be57ceac1e4692b41be9de6be8c32a106636dba4" + integrity sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@tybys/wasm-util@^0.10.0": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + +"@types/argparse@1.0.38": + version "1.0.38" + resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" + integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== + +"@types/babel__core@^7.1.14", "@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74" + integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q== + dependencies: + "@babel/types" "^7.28.2" + +"@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/hoist-non-react-statics@^3.3.6": + version "3.3.7" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz#306e3a3a73828522efa1341159da4846e7573a6c" + integrity sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g== + dependencies: + hoist-non-react-statics "^3.3.0" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@29.5.14": + version "29.5.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" + integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@*", "@types/node@24.10.1": + version "24.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.1.tgz#91e92182c93db8bd6224fca031e2370cef9a8f01" + integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ== + dependencies: + undici-types "~7.16.0" + +"@types/node@22.10.7": + version "22.10.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.7.tgz#14a1ca33fd0ebdd9d63593ed8d3fbc882a6d28d7" + integrity sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg== + dependencies: + undici-types "~6.20.0" + +"@types/react-dom@19.2.3", "@types/react-dom@^19.1.2": + version "19.2.3" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.2.3.tgz#c1e305d15a52a3e508d54dca770d202cb63abf2c" + integrity sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ== + +"@types/react-modal@3.16.3": + version "3.16.3" + resolved "https://registry.yarnpkg.com/@types/react-modal/-/react-modal-3.16.3.tgz#250f32c07f1de28e2bcf9c3e84b56adaa6897013" + integrity sha512-xXuGavyEGaFQDgBv4UVm8/ZsG+qxeQ7f77yNrW3n+1J6XAstUy5rYHeIHPh1KzsGc6IkCIdu6lQ2xWzu1jBTLg== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^19.1.2": + version "19.2.6" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.6.tgz#d27db1ff45012d53980f5589fda925278e1249ca" + integrity sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w== + dependencies: + csstype "^3.2.2" + +"@types/react@19.2.5": + version "19.2.5" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.5.tgz#bb75da5c52a956ba7d2623dffbba0fdadc3e4145" + integrity sha512-keKxkZMqnDicuvFoJbzrhbtdLSPhj/rZThDlKWCDbgXmUg0rEUFtRssDXKYmtXluZlIqiC5VqkCgRwzuyLHKHw== + dependencies: + csstype "^3.0.2" + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.35" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.35.tgz#07013e46aa4d7d7d50a49e15604c1c5340d4eb24" + integrity sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz#005dc4eebcb27462f20de3afe888065f65cec100" + integrity sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.46.4" + "@typescript-eslint/type-utils" "8.46.4" + "@typescript-eslint/utils" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/eslint-plugin@8.47.0", "@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz#c53edeec13a79483f4ca79c298d5231b02e9dc17" + integrity sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.47.0" + "@typescript-eslint/type-utils" "8.47.0" + "@typescript-eslint/utils" "8.47.0" + "@typescript-eslint/visitor-keys" "8.47.0" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/parser@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.4.tgz#1a5bfd48be57bc07eec64e090ac46e89f47ade31" + integrity sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w== + dependencies: + "@typescript-eslint/scope-manager" "8.46.4" + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/typescript-estree" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + debug "^4.3.4" + +"@typescript-eslint/parser@8.47.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.47.0.tgz#51b14ab2be2057ec0f57073b9ff3a9c078b0a964" + integrity sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ== + dependencies: + "@typescript-eslint/scope-manager" "8.47.0" + "@typescript-eslint/types" "8.47.0" + "@typescript-eslint/typescript-estree" "8.47.0" + "@typescript-eslint/visitor-keys" "8.47.0" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.4.tgz#fa9872673b51fb57e5d5da034edbe17424ddd185" + integrity sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.46.4" + "@typescript-eslint/types" "^8.46.4" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.47.0.tgz#b8afc65e0527568018af911b702dcfbfdca16471" + integrity sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.47.0" + "@typescript-eslint/types" "^8.47.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz#78c9b4856c0094def64ffa53ea955b46bec13304" + integrity sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA== + dependencies: + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + +"@typescript-eslint/scope-manager@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz#d1c36a973a5499fed3a99e2e6a66aec5c9b1e542" + integrity sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg== + dependencies: + "@typescript-eslint/types" "8.47.0" + "@typescript-eslint/visitor-keys" "8.47.0" + +"@typescript-eslint/tsconfig-utils@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz#989a338093b6b91b0552f1f51331d89ec6980382" + integrity sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A== + +"@typescript-eslint/tsconfig-utils@8.47.0", "@typescript-eslint/tsconfig-utils@^8.46.4", "@typescript-eslint/tsconfig-utils@^8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz#4f178b62813538759e0989dd081c5474fad39b84" + integrity sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g== + +"@typescript-eslint/type-utils@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz#ae71b428a3c138b5084affe47893c129949171e0" + integrity sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ== + dependencies: + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/typescript-estree" "8.46.4" + "@typescript-eslint/utils" "8.46.4" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/type-utils@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.47.0.tgz#b9b0141d99bd5bece3811d7eee68a002597ffa55" + integrity sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A== + dependencies: + "@typescript-eslint/types" "8.47.0" + "@typescript-eslint/typescript-estree" "8.47.0" + "@typescript-eslint/utils" "8.47.0" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/types@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.4.tgz#38022bfda051be80e4120eeefcd2b6e3e630a69b" + integrity sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w== + +"@typescript-eslint/types@8.47.0", "@typescript-eslint/types@^8.46.4", "@typescript-eslint/types@^8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.47.0.tgz#c7fc9b6642d03505f447a8392934b9d1850de5af" + integrity sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A== + +"@typescript-eslint/typescript-estree@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz#6a9eeab0da45bf400f22c818e0f47102a980ceaa" + integrity sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA== + dependencies: + "@typescript-eslint/project-service" "8.46.4" + "@typescript-eslint/tsconfig-utils" "8.46.4" + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + 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 "^2.1.0" + +"@typescript-eslint/typescript-estree@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz#86416dad58db76c4b3bd6a899b1381f9c388489a" + integrity sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg== + dependencies: + "@typescript-eslint/project-service" "8.47.0" + "@typescript-eslint/tsconfig-utils" "8.47.0" + "@typescript-eslint/types" "8.47.0" + "@typescript-eslint/visitor-keys" "8.47.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 "^2.1.0" + +"@typescript-eslint/utils@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.4.tgz#ea7878ddd625948cad4424dc2752b1be236556f5" + integrity sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.46.4" + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/typescript-estree" "8.46.4" + +"@typescript-eslint/utils@8.47.0", "@typescript-eslint/utils@^8.18.1", "@typescript-eslint/utils@^8.44.1": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.47.0.tgz#d6c30690431dbfdab98fc027202af12e77c91419" + integrity sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.47.0" + "@typescript-eslint/types" "8.47.0" + "@typescript-eslint/typescript-estree" "8.47.0" + +"@typescript-eslint/visitor-keys@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz#07031bd8d3ca6474e121221dae1055daead888f1" + integrity sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw== + dependencies: + "@typescript-eslint/types" "8.46.4" + eslint-visitor-keys "^4.2.1" + +"@typescript-eslint/visitor-keys@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz#35f36ed60a170dfc9d4d738e78387e217f24c29f" + integrity sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ== + dependencies: + "@typescript-eslint/types" "8.47.0" + eslint-visitor-keys "^4.2.1" + +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + +"@viselect/react@3.9.0": + version "3.9.0" + resolved "https://registry.yarnpkg.com/@viselect/react/-/react-3.9.0.tgz#d37bbb33d1759d625ba3be219ac299ddb9e67ccd" + integrity sha512-uz3ehdawjXwTUGnDKyNfmecviLAjUIG7cOQdeKcdXiSCHg9ZS12Vhr/j0shuHjX0xPvy9IqlbVuvzOHq77QDQw== + dependencies: + "@viselect/vanilla" "3.9.0" + +"@viselect/vanilla@3.9.0": + version "3.9.0" + resolved "https://registry.yarnpkg.com/@viselect/vanilla/-/vanilla-3.9.0.tgz#bddadfa2726ab9590edfe42dac0cd8e5cb01fd4e" + integrity sha512-E9eBgoi/crJ0SlZMAc+Yst7nU324LZ5LLvcXjzWEcrfllscdpTml2OLOKHC7O8Bbz19OybSLv6VexxnjlJrLxQ== + +"@vitejs/plugin-react-swc@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react-swc/-/plugin-react-swc-4.2.2.tgz#9818ed54318dcb0f254f6322c6bfbd0fcec2b087" + integrity sha512-x+rE6tsxq/gxrEJN3Nv3dIV60lFflPj94c90b+NNo6n1QV1QQUTLoL0MpaOVasUZ0zqVBn7ead1B5ecx1JAGfA== + dependencies: + "@rolldown/pluginutils" "1.0.0-beta.47" + "@swc/core" "^1.13.5" + +"@vitejs/plugin-react@^5.0.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz#fa1957e053fe90d7cc2deea5593ae382a9761595" + integrity sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA== + dependencies: + "@babel/core" "^7.28.5" + "@babel/plugin-transform-react-jsx-self" "^7.27.1" + "@babel/plugin-transform-react-jsx-source" "^7.27.1" + "@rolldown/pluginutils" "1.0.0-beta.47" + "@types/babel__core" "^7.20.5" + react-refresh "^0.18.0" + +"@volar/language-core@2.4.23", "@volar/language-core@~2.4.11": + version "2.4.23" + resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.4.23.tgz#deb6dbc5fdbafa9bb7ba691fc59cb196cdb856d3" + integrity sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ== + dependencies: + "@volar/source-map" "2.4.23" + +"@volar/source-map@2.4.23": + version "2.4.23" + resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.4.23.tgz#d476e11a3a669d89858a5eb38b02342be39b0e44" + integrity sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q== + +"@volar/typescript@^2.4.11": + version "2.4.23" + resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.4.23.tgz#b9b114ea01ad0ad977139edda0239fdafdb21ad7" + integrity sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag== + dependencies: + "@volar/language-core" "2.4.23" + path-browserify "^1.0.1" + vscode-uri "^3.0.8" + +"@vue/compiler-core@3.5.24": + version "3.5.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.24.tgz#1853f4b7d7090033cd9041aab6e7e8017d66c39c" + integrity sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig== + dependencies: + "@babel/parser" "^7.28.5" + "@vue/shared" "3.5.24" + entities "^4.5.0" + estree-walker "^2.0.2" + source-map-js "^1.2.1" + +"@vue/compiler-dom@^3.5.0": + version "3.5.24" + resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.24.tgz#b02e98749c377d6d2ba30dc2e94ce0f5b0af060c" + integrity sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw== + dependencies: + "@vue/compiler-core" "3.5.24" + "@vue/shared" "3.5.24" + +"@vue/compiler-vue2@^2.7.16": + version "2.7.16" + resolved "https://registry.yarnpkg.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz#2ba837cbd3f1b33c2bc865fbe1a3b53fb611e249" + integrity sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A== + dependencies: + de-indent "^1.0.2" + he "^1.2.0" + +"@vue/language-core@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.2.0.tgz#e48c54584f889f78b120ce10a050dfb316c7fcdf" + integrity sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw== + dependencies: + "@volar/language-core" "~2.4.11" + "@vue/compiler-dom" "^3.5.0" + "@vue/compiler-vue2" "^2.7.16" + "@vue/shared" "^3.5.0" + alien-signals "^0.4.9" + minimatch "^9.0.3" + muggle-string "^0.4.1" + path-browserify "^1.0.1" + +"@vue/shared@3.5.24", "@vue/shared@^3.5.0": + version "3.5.24" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.24.tgz#45ea9e6e037e53cfb8141ffa6bcad75b8be11e9c" + integrity sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.15.0, acorn@^8.4.1: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +ajv-draft-04@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + +ajv-formats@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +ajv@^8.0.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +ajv@~8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ajv@~8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91" + integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +alien-signals@^0.4.9: + version "0.4.14" + resolved "https://registry.yarnpkg.com/alien-signals/-/alien-signals-0.4.14.tgz#9ff8f72a272300a51692f54bd9bbbada78fbf539" + integrity sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q== + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7, argparse@~1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-hidden@^1.2.4: + version "1.2.6" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.6.tgz#73051c9b088114c795b1ea414e9c0fff874ffc1a" + integrity sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA== + dependencies: + tslib "^2.0.0" + +aria-query@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== + dependencies: + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-includes@^3.1.6, array-includes@^3.1.8, array-includes@^3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.9.tgz#1f0ccaa08e90cdbc3eb433210f903ad0f17c3f3a" + integrity sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-abstract "^1.24.0" + es-object-atoms "^1.1.1" + get-intrinsic "^1.3.0" + is-string "^1.1.1" + math-intrinsics "^1.1.0" + +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + 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" + +array.prototype.findlastindex@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz#cfa1065c81dcb64e34557c9b81d012f6a421c564" + integrity sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + es-shim-unscopables "^1.1.0" + +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + is-array-buffer "^3.0.4" + +ast-types-flow@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== + +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + +async@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + +attr-accept@^2.2.4: + version "2.2.5" + resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" + integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +axe-core@^4.10.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.11.0.tgz#16f74d6482e343ff263d4f4503829e9ee91a86b6" + integrity sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ== + +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +baseline-browser-mapping@^2.8.25: + version "2.8.29" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.29.tgz#d8800b71399c783cb1bf2068c2bcc3b6cfd7892c" + integrity sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA== + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.24.0: + version "4.28.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.0.tgz#9cefece0a386a17a3cd3d22ebf67b9deca1b5929" + integrity sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ== + dependencies: + baseline-browser-mapping "^2.8.25" + caniuse-lite "^1.0.30001754" + electron-to-chromium "^1.5.249" + node-releases "^2.0.27" + update-browserslist-db "^1.1.4" + +bs-logger@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001754: + version "1.0.30001756" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz#fe80104631102f88e58cad8aa203a2c3e5ec9ebd" + integrity sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A== + +chalk@4.1.2, chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +chromatic@11.28.2: + version "11.28.2" + resolved "https://registry.yarnpkg.com/chromatic/-/chromatic-11.28.2.tgz#c0b9f59dcc323ca8bf2c2790f3c9e3d285834efb" + integrity sha512-aCmUPcZUs4/p9zRZdMreOoO/5JqO2DiJC3md1/vRx8dlMRcmR/YI5ZbgXZcai2absVR+6hsXZ5XiPxV2sboTuQ== + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" + integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== + +classnames@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== + +client-only@0.0.1, client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clsx@2.1.1, clsx@^2.0.0, clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +cmdk@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.4.tgz#cbddef6f5ade2378f85c80a0b9ad9a8a712779b5" + integrity sha512-AnsjfHyHpQ/EFeAnG216WY7A5LiYCoZzCSygiLvfXC3H3LFGCprErteUcszaVluGOhuOTbJS3jWHrSDYPBBygg== + dependencies: + "@radix-ui/react-dialog" "^1.1.2" + "@radix-ui/react-id" "^1.1.0" + "@radix-ui/react-primitive" "^2.0.0" + use-sync-external-store "^1.2.2" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80" + integrity sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commander@13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + +compare-versions@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.1.tgz#7af3cc1099ba37d244b3145a9af5201b629148a9" + integrity sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg== + +compute-scroll-into-view@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz#02c3386ec531fb6a9881967388e53e8564f3e9aa" + integrity sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-js@^3, core-js@^3.38.1: + version "3.47.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.47.0.tgz#436ef07650e191afeb84c24481b298bd60eb4a17" + integrity sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg== + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +csstype@^3.0.2, csstype@^3.2.2: + version "3.2.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" + integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== + +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +decimal.js@^10.4.3: + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== + +dedent@^1.0.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.0.tgz#c1f9445335f0175a96587be245a282ff451446ca" + integrity sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@4.3.1, deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + +detect-libc@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diff@~8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-8.0.2.tgz#712156a6dd288e66ebb986864e190c2fc9eddfae" + integrity sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg== + +dnd-core@14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-14.0.1.tgz#76d000e41c494983210fb20a48b835f81a203c2e" + integrity sha512-+PVS2VPTgKFPYWo3vAFEA8WPbTf7/xo43TifH9G8S1KqnrQu0o77A3unrF5yOugy4mIz7K5wAVFHUcha7wsz6A== + dependencies: + "@react-dnd/asap" "^4.0.0" + "@react-dnd/invariant" "^2.0.0" + redux "^4.1.1" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +downshift@9.0.9: + version "9.0.9" + resolved "https://registry.yarnpkg.com/downshift/-/downshift-9.0.9.tgz#fd683a376a21bcc52f0d13d6cda47b4ea521f62b" + integrity sha512-ygOT8blgiz5liDuEFAIaPeU4dDEa+w9p6PHVUisPIjrkF5wfR59a52HpGWAVVMoWnoFO8po2mZSScKZueihS7g== + dependencies: + "@babel/runtime" "^7.24.5" + compute-scroll-into-view "^3.1.0" + prop-types "^15.8.1" + react-is "18.2.0" + tslib "^2.6.2" + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +ejs@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== + dependencies: + jake "^10.8.5" + +electron-to-chromium@^1.5.249: + version "1.5.256" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.256.tgz#f07f78de0893ab060f60ac897195c029a3b50d1a" + integrity sha512-uqYq1IQhpXXLX+HgiXdyOZml7spy4xfy42yPxcCCRjswp0fYM2X+JwCON07lqnpLEGVCj739B7Yr+FngmHBMEQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +entities@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +error-ex@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9, es-abstract@^1.24.0: + version "1.24.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.0.tgz#c44732d2beb0acc1ed60df840869e3106e7af328" + integrity sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg== + dependencies: + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.3.0" + get-proto "^1.0.1" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" + is-callable "^1.2.7" + is-data-view "^1.0.2" + is-negative-zero "^2.0.3" + is-regex "^1.2.1" + is-set "^2.0.3" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.1" + math-intrinsics "^1.1.0" + object-inspect "^1.13.4" + object-keys "^1.1.1" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.4" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + stop-iteration-iterator "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.19" + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-iterator-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" + integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.6" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es-shim-unscopables@^1.0.2, es-shim-unscopables@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== + dependencies: + hasown "^2.0.2" + +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +esbuild@^0.25.0: + version "0.25.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.12.tgz#97a1d041f4ab00c2fce2f838d2b9969a2d2a97a5" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-next@15.1.7: + version "15.1.7" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-15.1.7.tgz#80d287e6d1c0742304de8fe57cbc45000c455c11" + integrity sha512-zXoMnYUIy3XHaAoOhrcYkT9UQWvXqWju2K7NNsmb5wd/7XESDwof61eUdW4QhERr3eJ9Ko/vnXqIrj8kk/drYw== + dependencies: + "@next/eslint-plugin-next" "15.1.7" + "@rushstack/eslint-patch" "^1.10.3" + "@typescript-eslint/eslint-plugin" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + eslint-import-resolver-node "^0.3.6" + eslint-import-resolver-typescript "^3.5.2" + eslint-plugin-import "^2.31.0" + eslint-plugin-jsx-a11y "^6.10.0" + eslint-plugin-react "^7.37.0" + eslint-plugin-react-hooks "^5.0.0" + +eslint-config-prettier@10.1.8: + version "10.1.8" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#15734ce4af8c2778cc32f0b01b37b0b5cd1ecb97" + integrity sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w== + +eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-typescript@^3.5.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz#23dac32efa86a88e2b8232eb244ac499ad636db2" + integrity sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ== + dependencies: + "@nolyfill/is-core-module" "1.0.39" + debug "^4.4.0" + get-tsconfig "^4.10.0" + is-bun-module "^2.0.0" + stable-hash "^0.0.5" + tinyglobby "^0.2.13" + unrs-resolver "^1.6.2" + +eslint-module-utils@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz#f76d3220bfb83c057651359295ab5854eaad75ff" + integrity sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@^2.31.0: + version "2.32.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz#602b55faa6e4caeaa5e970c198b5c00a37708980" + integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA== + dependencies: + "@rtsao/scc" "^1.1.0" + array-includes "^3.1.9" + array.prototype.findlastindex "^1.2.6" + array.prototype.flat "^1.3.3" + array.prototype.flatmap "^1.3.3" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.12.1" + hasown "^2.0.2" + is-core-module "^2.16.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + object.groupby "^1.0.3" + object.values "^1.2.1" + semver "^6.3.1" + string.prototype.trimend "^1.0.9" + tsconfig-paths "^3.15.0" + +eslint-plugin-jsx-a11y@6.10.2, eslint-plugin-jsx-a11y@^6.10.0: + version "6.10.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz#d2812bb23bf1ab4665f1718ea442e8372e638483" + integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== + dependencies: + aria-query "^5.3.2" + array-includes "^3.1.8" + array.prototype.flatmap "^1.3.2" + ast-types-flow "^0.0.8" + axe-core "^4.10.0" + axobject-query "^4.1.0" + damerau-levenshtein "^1.0.8" + emoji-regex "^9.2.2" + hasown "^2.0.2" + jsx-ast-utils "^3.3.5" + language-tags "^1.0.9" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.1" + +eslint-plugin-react-hooks@7.0.1, eslint-plugin-react-hooks@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz#66e258db58ece50723ef20cc159f8aa908219169" + integrity sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA== + dependencies: + "@babel/core" "^7.24.4" + "@babel/parser" "^7.24.4" + hermes-parser "^0.25.1" + zod "^3.25.0 || ^4.0.0" + zod-validation-error "^3.5.0 || ^4.0.0" + +eslint-plugin-react-hooks@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz#1be0080901e6ac31ce7971beed3d3ec0a423d9e3" + integrity sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg== + +eslint-plugin-react-refresh@0.4.24, eslint-plugin-react-refresh@^0.4.19: + version "0.4.24" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz#6914e8757eb7d7ccc3efb9dbcc8a51feda71d89e" + integrity sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w== + +eslint-plugin-react@^7.37.0: + version "7.37.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz#2975511472bdda1b272b34d779335c9b0e877065" + integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.3" + array.prototype.tosorted "^1.1.4" + doctrine "^2.1.0" + es-iterator-helpers "^1.2.1" + estraverse "^5.3.0" + hasown "^2.0.2" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.9" + object.fromentries "^2.0.8" + object.values "^1.2.1" + prop-types "^15.8.1" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.12" + string.prototype.repeat "^1.0.0" + +eslint-scope@^8.2.0, eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@9.20.1: + version "9.20.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" + integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.19.0" + "@eslint/core" "^0.11.0" + "@eslint/eslintrc" "^3.2.0" + "@eslint/js" "9.20.0" + "@eslint/plugin-kit" "^0.2.5" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.1" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.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" + 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" + +eslint@9.39.1, eslint@^9.25.0: + version "9.39.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.1.tgz#be8bf7c6de77dcc4252b5a8dcb31c2efff74a6e5" + integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.39.1" + "@eslint/plugin-kit" "^0.4.1" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.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" + 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" + +espree@^10.0.1, espree@^10.3.0, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exenv@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw== + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +exsolve@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.8.tgz#7f5e34da61cd1116deda5136e62292c096f50613" + integrity sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + 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" + +fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fdir@^6.4.4, fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +fflate@^0.4.8: + version "0.4.8" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" + integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== + +figlet@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.8.1.tgz#e8e8a07e8c16be24c31086d7d5de8a9b9cf7f0fd" + integrity sha512-kEC3Sme+YvA8Hkibv0NR1oClGcWia0VB2fC1SlMy027cwe795Xx40Xiv/nw/iFAwQLupymWh+uhAAErn/7hwPg== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +file-selector@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" + integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== + dependencies: + tslib "^2.7.0" + +filelist@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + dependencies: + minimatch "^5.0.1" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + +for-each@^0.3.3, for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +fs-extra@~11.3.0: + version "11.3.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.2.tgz#c838aeddc6f4a8c74dd15f85e11fe5511bfe02a4" + integrity sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +generator-function@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.1.tgz#0e75dd410d1243687a0ba2e951b94eedb8f737a2" + integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + +get-tsconfig@^4.10.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + 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" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^16.0.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-16.5.0.tgz#ccf1594a437b97653b2be13ed4d8f5c9f850cac1" + integrity sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ== + +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hermes-estree@0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.25.1.tgz#6aeec17d1983b4eabf69721f3aa3eb705b17f480" + integrity sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw== + +hermes-parser@^0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.25.1.tgz#5be0e487b2090886c62bd8a11724cd766d5f54d1" + integrity sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA== + dependencies: + hermes-estree "0.25.1" + +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +i18next-browser-languagedetector@8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.0.tgz#c3ca311e249d2f7d8bb9b3b13ac9af380a3b15b0" + integrity sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g== + dependencies: + "@babel/runtime" "^7.23.2" + +i18next-fs-backend@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-2.6.1.tgz#bb352278136f47599783308df29f0a1b6a0d08b6" + integrity sha512-eYWTX7QT7kJ0sZyCPK6x1q+R63zvNKv2D6UdbMf15A8vNb2ZLyw4NNNZxPFwXlIv/U+oUtg8SakW6ZgJZcoqHQ== + +i18next@25.6.2: + version "25.6.2" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-25.6.2.tgz#d6de1a4be58242c7f0f1436ab2fa66c8f87b2e29" + integrity sha512-0GawNyVUw0yvJoOEBq1VHMAsqdM23XrHkMtl2gKEjviJQSLVXsrPqsoYAxBEugW5AB96I2pZkwRxyl8WZVoWdw== + dependencies: + "@babel/runtime" "^7.27.6" + +ignore@^5.2.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +ignore@^7.0.0: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + +immutable@^5.0.2: + version "5.1.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.4.tgz#e3f8c1fe7b567d56cf26698f31918c241dae8c1f" + integrity sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA== + +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-lazy@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== + +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" + +intl-messageformat@^10.1.0: + version "10.7.18" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.18.tgz#51a6f387afbca9b0f881b2ec081566db8c540b0d" + integrity sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/fast-memoize" "2.2.7" + "@formatjs/icu-messageformat-parser" "2.11.4" + tslib "^2.8.0" + +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-async-function@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== + dependencies: + async-function "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" + +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-bun-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-2.0.0.tgz#4d7859a87c0fcac950c95e666730e745eae8bddd" + integrity sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ== + dependencies: + semver "^7.7.1" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== + dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-generator-function@^1.0.10: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.2.tgz#ae3b61e3d5ea4e4839b90bad22b02335051a17d5" + integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== + dependencies: + call-bound "^1.0.4" + generator-function "^2.0.0" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== + dependencies: + call-bound "^1.0.3" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== + dependencies: + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" + +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== + dependencies: + call-bound "^1.0.3" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" + integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +iterator.prototype@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" + integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== + dependencies: + define-data-property "^1.1.4" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + get-proto "^1.0.0" + has-symbols "^1.1.0" + set-function-name "^2.0.2" + +jake@^10.8.5: + version "10.9.4" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.4.tgz#d626da108c63d5cfb00ab5c25fadc7e0084af8e6" + integrity sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA== + dependencies: + async "^3.2.6" + filelist "^1.0.4" + picocolors "^1.1.1" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +jju@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.2.tgz#77485ce1dd7f33c061fd1b16ecea23b55fcb04b0" + integrity sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonfile@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" + integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +language-subtag-registry@^0.3.20: + version "0.3.23" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== + +language-tags@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== + dependencies: + language-subtag-registry "^0.3.20" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +local-pkg@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" + integrity sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A== + dependencies: + mlly "^1.7.4" + pkg-types "^2.3.0" + quansync "^0.2.11" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@~4.17.15: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.0.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.30.17: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.1.1, make-error@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +"memoize-one@>=3.1.1 <6": + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.3.tgz#cf7a0314a16c4d9ab73a7730a0e8e3c3502d47aa" + integrity sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw== + dependencies: + "@isaacs/brace-expansion" "^5.0.0" + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.3, minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mlly@^1.7.4: + version "1.8.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" + integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== + dependencies: + acorn "^8.15.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + ufo "^1.6.1" + +ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +muggle-string@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" + integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== + +nanoid@^3.3.11, nanoid@^3.3.6: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +napi-postinstall@^0.3.0: + version "0.3.4" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.4.tgz#7af256d6588b5f8e952b9190965d6b019653bbb9" + integrity sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +next-i18next@15.4.2: + version "15.4.2" + resolved "https://registry.yarnpkg.com/next-i18next/-/next-i18next-15.4.2.tgz#b2bc80ad77e92433e6bf2821bbb76c2630347495" + integrity sha512-zgRxWf7kdXtM686ecGIBQL+Bq0+DqAhRlasRZ3vVF0TmrNTWkVhs52n//oU3Fj5O7r/xOKkECDUwfOuXVwTK/g== + dependencies: + "@babel/runtime" "^7.23.2" + "@types/hoist-non-react-statics" "^3.3.6" + core-js "^3" + hoist-non-react-statics "^3.3.2" + i18next-fs-backend "^2.6.0" + +next@15.4.9: + version "15.4.9" + resolved "https://registry.yarnpkg.com/next/-/next-15.4.9.tgz#9204500a9c3cb2b981fb932077abfa66d3ef663f" + integrity sha512-/NedNmbiH4Umt/7SohT9VKxEdBt02Lj33xHrukE7d8Li6juT+75sEq4a4U06jggrvdbklKgr78OZEyWZ8XRrtw== + dependencies: + "@next/env" "15.4.9" + "@swc/helpers" "0.5.15" + caniuse-lite "^1.0.30001579" + postcss "8.4.31" + styled-jsx "5.1.6" + optionalDependencies: + "@next/swc-darwin-arm64" "15.4.8" + "@next/swc-darwin-x64" "15.4.8" + "@next/swc-linux-arm64-gnu" "15.4.8" + "@next/swc-linux-arm64-musl" "15.4.8" + "@next/swc-linux-x64-gnu" "15.4.8" + "@next/swc-linux-x64-musl" "15.4.8" + "@next/swc-win32-arm64-msvc" "15.4.8" + "@next/swc-win32-x64-msvc" "15.4.8" + sharp "^0.34.3" + +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.3, object-inspect@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + +object.entries@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.9.tgz#e4770a6a1444afb61bd39f984018b5bede25f8b3" + integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-object-atoms "^1.1.1" + +object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.groupby@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + +object.values@^1.1.6, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + 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" + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2, picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pirates@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.3.0.tgz#037f2c19bd5402966ff6810e32706558cb5b5726" + integrity sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig== + dependencies: + confbox "^0.2.2" + exsolve "^1.0.7" + pathe "^2.0.3" + +playwright-core@1.56.1: + version "1.56.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.56.1.tgz#24a66481e5cd33a045632230aa2c4f0cb6b1db3d" + integrity sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ== + +playwright@1.56.1: + version "1.56.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.56.1.tgz#62e3b99ddebed0d475e5936a152c88e68be55fbf" + integrity sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw== + dependencies: + playwright-core "1.56.1" + optionalDependencies: + fsevents "2.3.2" + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss@8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +postcss@^8.4.43, postcss@^8.5.3: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +posthog-js@1.293.0: + version "1.293.0" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.293.0.tgz#ba662ea9953cdcdbd3f418880bb4bb68f5a04bf1" + integrity sha512-0KN3gVNbZPwEEWe5w6VH5Ql/+y113mwsl5TTEpOlAtN1ae6Ok18mQ6cS2K0X56GpF/dtdSoXQtnex6ZqUcdAcA== + dependencies: + "@posthog/core" "1.5.2" + core-js "^3.38.1" + fflate "^0.4.8" + preact "^10.19.3" + web-vitals "^4.2.4" + +preact@^10.19.3: + version "10.27.2" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.27.2.tgz#19b9009c1be801a76a0aaf0fe5ba665985a09312" + integrity sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" + integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== + +pretty-bytes@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-7.1.0.tgz#d788c9906241dbdcd4defab51b6d7470243db9bd" + integrity sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw== + +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== + +quansync@^0.2.11: + version "0.2.11" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.11.tgz#f9c3adda2e1272e4f8cf3f1457b04cbdb4ee692a" + integrity sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-arborist@3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/react-arborist/-/react-arborist-3.4.3.tgz#982791a07d1e279f279be88162c920112f3cee90" + integrity sha512-yFnq1nIQhT2uJY4TZVz2tgAiBb9lxSyvF4vC3S8POCK8xLzjGIxVv3/4dmYquQJ7AHxaZZArRGHiHKsEewKdTQ== + dependencies: + react-dnd "^14.0.3" + react-dnd-html5-backend "^14.0.3" + react-window "^1.8.11" + redux "^5.0.0" + use-sync-external-store "^1.2.0" + +react-aria-components@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/react-aria-components/-/react-aria-components-1.8.0.tgz#db8744ceae1d117d06f73b3de29b716a8b4ef7c3" + integrity sha512-qNJ/Z4opj1/NKFf1ch/V8rNYar5MXu4J8YVAt2pFgnBRLjVlIlfnENN8Oa5OFiYFCzMPRFdq5mI8RuYIEnvZfg== + dependencies: + "@internationalized/date" "^3.8.0" + "@internationalized/string" "^3.2.6" + "@react-aria/autocomplete" "3.0.0-beta.2" + "@react-aria/collections" "3.0.0-rc.0" + "@react-aria/dnd" "^3.9.2" + "@react-aria/focus" "^3.20.2" + "@react-aria/interactions" "^3.25.0" + "@react-aria/live-announcer" "^3.4.2" + "@react-aria/overlays" "^3.27.0" + "@react-aria/ssr" "^3.9.8" + "@react-aria/toolbar" "3.0.0-beta.15" + "@react-aria/utils" "^3.28.2" + "@react-aria/virtualizer" "^4.1.4" + "@react-stately/autocomplete" "3.0.0-beta.1" + "@react-stately/layout" "^4.2.2" + "@react-stately/selection" "^3.20.1" + "@react-stately/table" "^3.14.1" + "@react-stately/utils" "^3.10.6" + "@react-stately/virtualizer" "^4.3.2" + "@react-types/form" "^3.7.11" + "@react-types/grid" "^3.3.1" + "@react-types/shared" "^3.29.0" + "@react-types/table" "^3.12.0" + "@swc/helpers" "^0.5.0" + client-only "^0.0.1" + react-aria "^3.39.0" + react-stately "^3.37.0" + use-sync-external-store "^1.4.0" + +react-aria@3.39.0: + version "3.39.0" + resolved "https://registry.yarnpkg.com/react-aria/-/react-aria-3.39.0.tgz#68e01a25365f403cfbc870b7ec29093d8722f0ba" + integrity sha512-zXCjR01WnfW4uW0f294uWrvdfwEMHgDFSwMwMBwRafAvmsQea87X5VTAfDmQOAbPa+iQFcngIyH0Pn5CfXNrjw== + dependencies: + "@internationalized/string" "^3.2.6" + "@react-aria/breadcrumbs" "^3.5.23" + "@react-aria/button" "^3.13.0" + "@react-aria/calendar" "^3.8.0" + "@react-aria/checkbox" "^3.15.4" + "@react-aria/color" "^3.0.6" + "@react-aria/combobox" "^3.12.2" + "@react-aria/datepicker" "^3.14.2" + "@react-aria/dialog" "^3.5.24" + "@react-aria/disclosure" "^3.0.4" + "@react-aria/dnd" "^3.9.2" + "@react-aria/focus" "^3.20.2" + "@react-aria/gridlist" "^3.12.0" + "@react-aria/i18n" "^3.12.8" + "@react-aria/interactions" "^3.25.0" + "@react-aria/label" "^3.7.17" + "@react-aria/landmark" "^3.0.2" + "@react-aria/link" "^3.8.0" + "@react-aria/listbox" "^3.14.3" + "@react-aria/menu" "^3.18.2" + "@react-aria/meter" "^3.4.22" + "@react-aria/numberfield" "^3.11.13" + "@react-aria/overlays" "^3.27.0" + "@react-aria/progress" "^3.4.22" + "@react-aria/radio" "^3.11.2" + "@react-aria/searchfield" "^3.8.3" + "@react-aria/select" "^3.15.4" + "@react-aria/selection" "^3.24.0" + "@react-aria/separator" "^3.4.8" + "@react-aria/slider" "^3.7.18" + "@react-aria/ssr" "^3.9.8" + "@react-aria/switch" "^3.7.2" + "@react-aria/table" "^3.17.2" + "@react-aria/tabs" "^3.10.2" + "@react-aria/tag" "^3.5.2" + "@react-aria/textfield" "^3.17.2" + "@react-aria/toast" "^3.0.2" + "@react-aria/tooltip" "^3.8.2" + "@react-aria/tree" "^3.0.2" + "@react-aria/utils" "^3.28.2" + "@react-aria/visually-hidden" "^3.8.22" + "@react-types/shared" "^3.29.0" + +react-aria@^3.39.0: + version "3.44.0" + resolved "https://registry.yarnpkg.com/react-aria/-/react-aria-3.44.0.tgz#6b694c704c0d438feb1baad23ab32cc7e8edb68f" + integrity sha512-2Pq3GQxBgM4/2BlpKYXeaZ47a3tdIcYSW/AYvKgypE3XipxOdQMDG5Sr/NBn7zuJq+thzmtfRb0lB9bTbsmaRw== + dependencies: + "@internationalized/string" "^3.2.7" + "@react-aria/breadcrumbs" "^3.5.29" + "@react-aria/button" "^3.14.2" + "@react-aria/calendar" "^3.9.2" + "@react-aria/checkbox" "^3.16.2" + "@react-aria/color" "^3.1.2" + "@react-aria/combobox" "^3.14.0" + "@react-aria/datepicker" "^3.15.2" + "@react-aria/dialog" "^3.5.31" + "@react-aria/disclosure" "^3.1.0" + "@react-aria/dnd" "^3.11.3" + "@react-aria/focus" "^3.21.2" + "@react-aria/gridlist" "^3.14.1" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/landmark" "^3.0.7" + "@react-aria/link" "^3.8.6" + "@react-aria/listbox" "^3.15.0" + "@react-aria/menu" "^3.19.3" + "@react-aria/meter" "^3.4.27" + "@react-aria/numberfield" "^3.12.2" + "@react-aria/overlays" "^3.30.0" + "@react-aria/progress" "^3.4.27" + "@react-aria/radio" "^3.12.2" + "@react-aria/searchfield" "^3.8.9" + "@react-aria/select" "^3.17.0" + "@react-aria/selection" "^3.26.0" + "@react-aria/separator" "^3.4.13" + "@react-aria/slider" "^3.8.2" + "@react-aria/ssr" "^3.9.10" + "@react-aria/switch" "^3.7.8" + "@react-aria/table" "^3.17.8" + "@react-aria/tabs" "^3.10.8" + "@react-aria/tag" "^3.7.2" + "@react-aria/textfield" "^3.18.2" + "@react-aria/toast" "^3.0.8" + "@react-aria/tooltip" "^3.8.8" + "@react-aria/tree" "^3.1.4" + "@react-aria/utils" "^3.31.0" + "@react-aria/visually-hidden" "^3.8.28" + "@react-types/shared" "^3.32.1" + +react-dnd-html5-backend@^14.0.3: + version "14.1.0" + resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-14.1.0.tgz#b35a3a0c16dd3a2bfb5eb7ec62cf0c2cace8b62f" + integrity sha512-6ONeqEC3XKVf4eVmMTe0oPds+c5B9Foyj8p/ZKLb7kL2qh9COYxiBHv3szd6gztqi/efkmriywLUVlPotqoJyw== + dependencies: + dnd-core "14.0.1" + +react-dnd@^14.0.3: + version "14.0.5" + resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-14.0.5.tgz#ecf264e220ae62e35634d9b941502f3fca0185ed" + integrity sha512-9i1jSgbyVw0ELlEVt/NkCUkxy1hmhJOkePoCH713u75vzHGyXhPDm28oLfc2NMSBjZRM1Y+wRjHXJT3sPrTy+A== + dependencies: + "@react-dnd/invariant" "^2.0.0" + "@react-dnd/shallowequal" "^2.0.0" + dnd-core "14.0.1" + fast-deep-equal "^3.1.3" + hoist-non-react-statics "^3.3.2" + +react-dom@19.2.0: + version "19.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.0.tgz#00ed1e959c365e9a9d48f8918377465466ec3af8" + integrity sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ== + dependencies: + scheduler "^0.27.0" + +react-dropzone@14.3.8: + version "14.3.8" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.3.8.tgz#a7eab118f8a452fe3f8b162d64454e81ba830582" + integrity sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug== + dependencies: + attr-accept "^2.2.4" + file-selector "^2.1.0" + prop-types "^15.8.1" + +react-hook-form@7.66.0: + version "7.66.0" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.66.0.tgz#1a09ea9d0ebb3bdda5073b08a486538d37d9c0d4" + integrity sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw== + +react-i18next@16.3.3: + version "16.3.3" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-16.3.3.tgz#098ff5443d0436a78692ca76303b2219aca32989" + integrity sha512-IaY2W+ueVd/fe7H6Wj2S4bTuLNChnajFUlZFfCTrTHWzGcOrUHlVzW55oXRSl+J51U8Onn6EvIhQ+Bar9FUcjw== + dependencies: + "@babel/runtime" "^7.27.6" + html-parse-stringify "^3.0.1" + use-sync-external-store "^1.6.0" + +react-is@18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +react-lifecycles-compat@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-modal@3.16.3: + version "3.16.3" + resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.3.tgz#c412d41915782e3c261253435d01468e2439b11b" + integrity sha512-yCYRJB5YkeQDQlTt17WGAgFJ7jr2QYcWa1SHqZ3PluDmnKJ/7+tVU+E6uKyZ0nODaeEj+xCpK4LcSnKXLMC0Nw== + dependencies: + exenv "^1.2.0" + prop-types "^15.7.2" + react-lifecycles-compat "^3.0.0" + warning "^4.0.3" + +react-refresh@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.18.0.tgz#2dce97f4fe932a4d8142fa1630e475c1729c8062" + integrity sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw== + +react-remove-scroll-bar@^2.3.7: + version "2.3.8" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== + dependencies: + react-style-singleton "^2.2.2" + tslib "^2.0.0" + +react-remove-scroll@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz#d2101d414f6d81d7d3bf033f3c1cb4785789f753" + integrity sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA== + dependencies: + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" + tslib "^2.1.0" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" + +react-resizable-panels@2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/react-resizable-panels/-/react-resizable-panels-2.1.7.tgz#afd29d8a3d708786a9f95183a38803c89f13c2e7" + integrity sha512-JtT6gI+nURzhMYQYsx8DKkx6bSoOGFp7A3CwMrOb8y5jFHFyqwo9m68UhmXRw57fRVJksFn1TSlm3ywEQ9vMgA== + +react-stately@3.37.0: + version "3.37.0" + resolved "https://registry.yarnpkg.com/react-stately/-/react-stately-3.37.0.tgz#9bd09ecd1c7b11461ec60e17a7c670c17a64962e" + integrity sha512-fm2LRM3XN5lJD48+WQKWvESx54kAIHw0JztCRHMsFmTDgYWX/VASuXKON7LECv227stSEadrxGa8LhPkcelljw== + dependencies: + "@react-stately/calendar" "^3.8.0" + "@react-stately/checkbox" "^3.6.13" + "@react-stately/collections" "^3.12.3" + "@react-stately/color" "^3.8.4" + "@react-stately/combobox" "^3.10.4" + "@react-stately/data" "^3.12.3" + "@react-stately/datepicker" "^3.14.0" + "@react-stately/disclosure" "^3.0.3" + "@react-stately/dnd" "^3.5.3" + "@react-stately/form" "^3.1.3" + "@react-stately/list" "^3.12.1" + "@react-stately/menu" "^3.9.3" + "@react-stately/numberfield" "^3.9.11" + "@react-stately/overlays" "^3.6.15" + "@react-stately/radio" "^3.10.12" + "@react-stately/searchfield" "^3.5.11" + "@react-stately/select" "^3.6.12" + "@react-stately/selection" "^3.20.1" + "@react-stately/slider" "^3.6.3" + "@react-stately/table" "^3.14.1" + "@react-stately/tabs" "^3.8.1" + "@react-stately/toast" "^3.1.0" + "@react-stately/toggle" "^3.8.3" + "@react-stately/tooltip" "^3.5.3" + "@react-stately/tree" "^3.8.9" + "@react-types/shared" "^3.29.0" + +react-stately@^3.37.0: + version "3.42.0" + resolved "https://registry.yarnpkg.com/react-stately/-/react-stately-3.42.0.tgz#f309e9cb729374cc187c688529a2aa0572ab9408" + integrity sha512-lYt2o1dd6dK8Bb4GRh08RG/2u64bSA1cqtRqtw4jEMgxC7Q17RFcIumBbChErndSdLzafEG/UBwV6shOfig6yw== + dependencies: + "@react-stately/calendar" "^3.9.0" + "@react-stately/checkbox" "^3.7.2" + "@react-stately/collections" "^3.12.8" + "@react-stately/color" "^3.9.2" + "@react-stately/combobox" "^3.12.0" + "@react-stately/data" "^3.14.1" + "@react-stately/datepicker" "^3.15.2" + "@react-stately/disclosure" "^3.0.8" + "@react-stately/dnd" "^3.7.1" + "@react-stately/form" "^3.2.2" + "@react-stately/list" "^3.13.1" + "@react-stately/menu" "^3.9.8" + "@react-stately/numberfield" "^3.10.2" + "@react-stately/overlays" "^3.6.20" + "@react-stately/radio" "^3.11.2" + "@react-stately/searchfield" "^3.5.16" + "@react-stately/select" "^3.8.0" + "@react-stately/selection" "^3.20.6" + "@react-stately/slider" "^3.7.2" + "@react-stately/table" "^3.15.1" + "@react-stately/tabs" "^3.8.6" + "@react-stately/toast" "^3.1.2" + "@react-stately/toggle" "^3.9.2" + "@react-stately/tooltip" "^3.5.8" + "@react-stately/tree" "^3.9.3" + "@react-types/shared" "^3.32.1" + +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== + dependencies: + get-nonce "^1.0.0" + tslib "^2.0.0" + +react-toastify@11.0.5: + version "11.0.5" + resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-11.0.5.tgz#ce4c42d10eeb433988ab2264d3e445c4e9d13313" + integrity sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA== + dependencies: + clsx "^2.1.1" + +react-window@^1.8.11: + version "1.8.11" + resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.11.tgz#a857b48fa85bd77042d59cc460964ff2e0648525" + integrity sha512-+SRbUVT2scadgFSWx+R1P754xHPEqvcfSfVX10QYg6POOz+WNgkN48pS+BtZNIMGiL1HYrSEiCkwsMS15QogEQ== + dependencies: + "@babel/runtime" "^7.0.0" + memoize-one ">=3.1.1 <6" + +react@19.2.0: + version "19.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.2.0.tgz#d33dd1721698f4376ae57a54098cb47fc75d93a5" + integrity sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ== + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +redux@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + +redux@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" + integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== + +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" + +regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-errors "^1.3.0" + get-proto "^1.0.1" + gopd "^1.2.0" + set-function-name "^2.0.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve.exports@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" + integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== + +resolve@^1.20.0, resolve@^1.22.4, resolve@~1.22.1, resolve@~1.22.2: + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== + dependencies: + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rollup@^4.20.0, rollup@^4.34.9: + version "4.53.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.53.3.tgz#dbc8cd8743b38710019fb8297e8d7a76e3faa406" + integrity sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.53.3" + "@rollup/rollup-android-arm64" "4.53.3" + "@rollup/rollup-darwin-arm64" "4.53.3" + "@rollup/rollup-darwin-x64" "4.53.3" + "@rollup/rollup-freebsd-arm64" "4.53.3" + "@rollup/rollup-freebsd-x64" "4.53.3" + "@rollup/rollup-linux-arm-gnueabihf" "4.53.3" + "@rollup/rollup-linux-arm-musleabihf" "4.53.3" + "@rollup/rollup-linux-arm64-gnu" "4.53.3" + "@rollup/rollup-linux-arm64-musl" "4.53.3" + "@rollup/rollup-linux-loong64-gnu" "4.53.3" + "@rollup/rollup-linux-ppc64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-musl" "4.53.3" + "@rollup/rollup-linux-s390x-gnu" "4.53.3" + "@rollup/rollup-linux-x64-gnu" "4.53.3" + "@rollup/rollup-linux-x64-musl" "4.53.3" + "@rollup/rollup-openharmony-arm64" "4.53.3" + "@rollup/rollup-win32-arm64-msvc" "4.53.3" + "@rollup/rollup-win32-ia32-msvc" "4.53.3" + "@rollup/rollup-win32-x64-gnu" "4.53.3" + "@rollup/rollup-win32-x64-msvc" "4.53.3" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" + isarray "^2.0.5" + +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== + dependencies: + es-errors "^1.3.0" + isarray "^2.0.5" + +safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +sass@1.94.0: + version "1.94.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.94.0.tgz#a04198d8940358ca6ad537d2074051edbbe7c1a7" + integrity sha512-Dqh7SiYcaFtdv5Wvku6QgS5IGPm281L+ZtVD1U2FJa7Q0EFRlq8Z3sjYtz6gYObsYThUOz9ArwFqPZx+1azILQ== + dependencies: + chokidar "^4.0.0" + immutable "^5.0.2" + source-map-js ">=0.6.2 <2.0.0" + optionalDependencies: + "@parcel/watcher" "^2.4.1" + +scheduler@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.27.0.tgz#0c4ef82d67d1e5c1e359e8fc76d3a87f045fe5bd" + integrity sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q== + +semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@^7.7.1, semver@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + +semver@~7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + 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" + +set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + +sharp@^0.34.3: + version "0.34.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.34.5.tgz#b6f148e4b8c61f1797bde11a9d1cfebbae2c57b0" + integrity sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg== + dependencies: + "@img/colour" "^1.0.0" + detect-libc "^2.1.2" + semver "^7.7.3" + optionalDependencies: + "@img/sharp-darwin-arm64" "0.34.5" + "@img/sharp-darwin-x64" "0.34.5" + "@img/sharp-libvips-darwin-arm64" "1.2.4" + "@img/sharp-libvips-darwin-x64" "1.2.4" + "@img/sharp-libvips-linux-arm" "1.2.4" + "@img/sharp-libvips-linux-arm64" "1.2.4" + "@img/sharp-libvips-linux-ppc64" "1.2.4" + "@img/sharp-libvips-linux-riscv64" "1.2.4" + "@img/sharp-libvips-linux-s390x" "1.2.4" + "@img/sharp-libvips-linux-x64" "1.2.4" + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" + "@img/sharp-linux-arm" "0.34.5" + "@img/sharp-linux-arm64" "0.34.5" + "@img/sharp-linux-ppc64" "0.34.5" + "@img/sharp-linux-riscv64" "0.34.5" + "@img/sharp-linux-s390x" "0.34.5" + "@img/sharp-linux-x64" "0.34.5" + "@img/sharp-linuxmusl-arm64" "0.34.5" + "@img/sharp-linuxmusl-x64" "0.34.5" + "@img/sharp-wasm32" "0.34.5" + "@img/sharp-win32-arm64" "0.34.5" + "@img/sharp-win32-ia32" "0.34.5" + "@img/sharp-win32-x64" "0.34.5" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stable-hash@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.5.tgz#94e8837aaeac5b4d0f631d2972adef2924b40269" + integrity sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +stop-iteration-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" + integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== + dependencies: + es-errors "^1.3.0" + internal-slot "^1.1.0" + +string-argv@~0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" + integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.includes@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" + integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + +string.prototype.matchall@^4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" + integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + regexp.prototype.flags "^1.5.3" + set-function-name "^2.0.2" + side-channel "^1.1.0" + +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" + +string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +styled-jsx@5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.6.tgz#83b90c077e6c6a80f7f5e8781d0f311b2fe41499" + integrity sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA== + dependencies: + client-only "0.0.1" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0, supports-color@~8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +tinyglobby@^0.2.13: + version "0.2.15" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.3" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + +ts-jest@29.2.5: + version "29.2.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" + integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== + dependencies: + bs-logger "^0.2.6" + ejs "^3.1.10" + fast-json-stable-stringify "^2.1.0" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.6.3" + yargs-parser "^21.1.1" + +ts-node@10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +turbo-darwin-64@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.6.1.tgz#62be8b3033c166103c6e6368bc37a29ebd9f5a1e" + integrity sha512-Dm0HwhyZF4J0uLqkhUyCVJvKM9Rw7M03v3J9A7drHDQW0qAbIGBrUijQ8g4Q9Cciw/BXRRd8Uzkc3oue+qn+ZQ== + +turbo-darwin-arm64@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo-darwin-arm64/-/turbo-darwin-arm64-2.6.1.tgz#41482448cd40f226237d97ca1892572f93d488e5" + integrity sha512-U0PIPTPyxdLsrC3jN7jaJUwgzX5sVUBsKLO7+6AL+OASaa1NbT1pPdiZoTkblBAALLP76FM0LlnsVQOnmjYhyw== + +turbo-linux-64@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo-linux-64/-/turbo-linux-64-2.6.1.tgz#1b47a28a3387858eb9c17ff77660180265074659" + integrity sha512-eM1uLWgzv89bxlK29qwQEr9xYWBhmO/EGiH22UGfq+uXr+QW1OvNKKMogSN65Ry8lElMH4LZh0aX2DEc7eC0Mw== + +turbo-linux-arm64@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo-linux-arm64/-/turbo-linux-arm64-2.6.1.tgz#7cc9b42c70cc37f8799312c586a914bd8b78c944" + integrity sha512-MFFh7AxAQAycXKuZDrbeutfWM5Ep0CEZ9u7zs4Hn2FvOViTCzIfEhmuJou3/a5+q5VX1zTxQrKGy+4Lf5cdpsA== + +turbo-windows-64@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo-windows-64/-/turbo-windows-64-2.6.1.tgz#c367296dd5f1465f1a1071ac987ba179b956531a" + integrity sha512-buq7/VAN7KOjMYi4tSZT5m+jpqyhbRU2EUTTvp6V0Ii8dAkY2tAAjQN1q5q2ByflYWKecbQNTqxmVploE0LVwQ== + +turbo-windows-arm64@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo-windows-arm64/-/turbo-windows-arm64-2.6.1.tgz#530eafbcf46a2b7ed2f183a6a32a25a9c8901287" + integrity sha512-7w+AD5vJp3R+FB0YOj1YJcNcOOvBior7bcHTodqp90S3x3bLgpr7tE6xOea1e8JkP7GK6ciKVUpQvV7psiwU5Q== + +turbo@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/turbo/-/turbo-2.6.1.tgz#12107e157f49e6bb3fbcf54025d55fd7f30b9c7c" + integrity sha512-qBwXXuDT3rA53kbNafGbT5r++BrhRgx3sAo0cHoDAeG9g1ItTmUMgltz3Hy7Hazy1ODqNpR+C7QwqL6DYB52yA== + optionalDependencies: + turbo-darwin-64 "2.6.1" + turbo-darwin-arm64 "2.6.1" + turbo-linux-64 "2.6.1" + turbo-linux-arm64 "2.6.1" + turbo-windows-64 "2.6.1" + turbo-windows-arm64 "2.6.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== + dependencies: + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" + +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" + +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" + +typescript-eslint@^8.30.1: + version "8.47.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.47.0.tgz#bb8fcf4f2c69ffcd5d088f7f30cd52936ff05cbc" + integrity sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q== + dependencies: + "@typescript-eslint/eslint-plugin" "8.47.0" + "@typescript-eslint/parser" "8.47.0" + "@typescript-eslint/typescript-estree" "8.47.0" + "@typescript-eslint/utils" "8.47.0" + +typescript@5.4.5: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + +typescript@5.8.2: + version "5.8.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== + +typescript@5.9.3, typescript@~5.9.0: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +ufo@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== + dependencies: + call-bound "^1.0.3" + has-bigints "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" + +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unrs-resolver@^1.6.2: + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + +update-browserslist-db@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a" + integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +uri-js@^4.2.2, uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +use-callback-ref@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== + dependencies: + tslib "^2.0.0" + +use-sidecar@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@^1.2.0, use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0, use-sync-external-store@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" + integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +vite-plugin-dts@4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/vite-plugin-dts/-/vite-plugin-dts-4.5.4.tgz#51b60aaaa760d9cf5c2bb3676c69d81910d6b08c" + integrity sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg== + dependencies: + "@microsoft/api-extractor" "^7.50.1" + "@rollup/pluginutils" "^5.1.4" + "@volar/typescript" "^2.4.11" + "@vue/language-core" "2.2.0" + compare-versions "^6.1.1" + debug "^4.4.0" + kolorist "^1.8.0" + local-pkg "^1.0.0" + magic-string "^0.30.17" + +vite@5.4.21: + version "5.4.21" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.21.tgz#84a4f7c5d860b071676d39ba513c0d598fdc7027" + integrity sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +vite@^6.3.5: + version "6.4.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.1.tgz#afbe14518cdd6887e240a4b0221ab6d0ce733f96" + integrity sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== + +vscode-uri@^3.0.8: + version "3.1.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +warning@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + +web-vitals@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" + integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== + +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + dependencies: + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" + +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.16, which-typed-array@^1.1.19: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +"zod-validation-error@^3.5.0 || ^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-4.0.2.tgz#bc605eba49ce0fcd598c127fee1c236be3f22918" + integrity sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ== + +"zod@^3.25.0 || ^4.0.0": + version "4.1.12" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0" + integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ== diff --git a/src/nginx/servers.conf.erb b/src/nginx/servers.conf.erb new file mode 100644 index 0000000..c003d9d --- /dev/null +++ b/src/nginx/servers.conf.erb @@ -0,0 +1,54 @@ +# ERB templated nginx configuration +# see https://doc.scalingo.com/platform/deployment/buildpacks/nginx + +upstream backend_server { + server localhost:8000 fail_timeout=0; +} + +server { + + listen <%= ENV["PORT"] %>; + server_name _; + + root /app/build/frontend-out; + + error_page 404 /404.html; + + # Django rest framework and external API + location ~ ^/(api|external_api)/ { + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_redirect off; + proxy_pass http://backend_server; + } + + # Django admin + location ^~ /admin/ { + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_redirect off; + proxy_pass http://backend_server; + } + + location ~ "^/401/?$" { + try_files $uri /401.html; + } + + location ~ "^/403/?$" { + try_files $uri /403.html; + } + + location = /404.html { + internal; + } + + # Frontend export + location / { + try_files $uri index.html $uri/ =404; + } + +}