From 952b2943450344ef593e64d7c06ce48c2cc6e79d Mon Sep 17 00:00:00 2001 From: Untone Date: Mon, 30 Jun 2025 21:25:26 +0300 Subject: [PATCH] 0.5.8-panel-upgrade-community-crud-fix --- .gitignore | 5 + CHANGELOG.md | 156 +- auth/decorators.py | 117 +- auth/oauth.py | 4 +- biome.json | 60 +- cache/cache.py | 98 +- codegen.ts | 38 + docs/README.md | 8 + docs/features.md | 45 + docs/follower.md | 2 +- docs/oauth-deployment.md | 2 +- docs/oauth.md | 2 +- orm/community.py | 3 +- package-lock.json | 4501 ++++++++++++++++++++++- package.json | 35 +- panel/App.tsx | 170 +- panel/admin.tsx | 1734 +-------- panel/{ => assets}/discours.svg | 0 panel/{ => assets}/publy.svg | 0 panel/auth.ts | 177 - panel/context/auth.tsx | 150 + panel/graphql.ts | 208 -- panel/graphql/index.ts | 139 + panel/graphql/mutations.ts | 63 + panel/graphql/queries.ts | 156 + panel/login.tsx | 121 - panel/modals/EnvVariableModal.tsx | 188 + panel/modals/RolesModal.tsx | 272 ++ panel/modals/ShoutBodyModal.tsx | 52 + panel/modals/TopicEditModal.tsx | 185 + panel/routes/authors.tsx | 283 ++ panel/routes/communities.tsx | 381 ++ panel/routes/env.tsx | 275 ++ panel/routes/login.tsx | 89 + panel/routes/shouts.tsx | 317 ++ panel/routes/topics.tsx | 410 +++ panel/styles.css | 266 +- panel/styles/Admin.module.css | 544 +++ panel/styles/Button.module.css | 94 + panel/styles/CodePreview.module.css | 138 + panel/styles/Form.module.css | 441 +++ panel/styles/GlobalVariables.module.css | 101 + panel/styles/Loading.module.css | 0 panel/styles/Login.module.css | 78 + panel/styles/Modal.module.css | 228 ++ panel/styles/Pagination.module.css | 114 + panel/styles/Table.module.css | 209 ++ panel/styles/Utilities.module.css | 72 + panel/types/css.d.ts | 4 + panel/types/svg.d.ts | 15 + panel/ui/Button.tsx | 35 + panel/ui/CodePreview.tsx | 103 + panel/ui/EditableCodePreview.tsx | 266 ++ panel/ui/Modal.tsx | 48 + panel/ui/Pagination.tsx | 117 + panel/ui/TextPreview.tsx | 64 + panel/utils/auth.ts | 99 + panel/utils/date.ts | 104 + pylanceconfig.json | 36 +- resolvers/admin.py | 47 +- resolvers/community.py | 247 +- resolvers/topic.py | 53 + schema/admin.graphql | 5 +- schema/input.graphql | 2 + schema/mutation.graphql | 1 + schema/query.graphql | 2 +- schema/type.graphql | 2 + services/schema.py | 3 +- tsconfig.json | 6 +- vite.config.ts | 10 +- 70 files changed, 11345 insertions(+), 2655 deletions(-) create mode 100644 codegen.ts rename panel/{ => assets}/discours.svg (100%) rename panel/{ => assets}/publy.svg (100%) delete mode 100644 panel/auth.ts create mode 100644 panel/context/auth.tsx delete mode 100644 panel/graphql.ts create mode 100644 panel/graphql/index.ts create mode 100644 panel/graphql/mutations.ts create mode 100644 panel/graphql/queries.ts delete mode 100644 panel/login.tsx create mode 100644 panel/modals/EnvVariableModal.tsx create mode 100644 panel/modals/RolesModal.tsx create mode 100644 panel/modals/ShoutBodyModal.tsx create mode 100644 panel/modals/TopicEditModal.tsx create mode 100644 panel/routes/authors.tsx create mode 100644 panel/routes/communities.tsx create mode 100644 panel/routes/env.tsx create mode 100644 panel/routes/login.tsx create mode 100644 panel/routes/shouts.tsx create mode 100644 panel/routes/topics.tsx create mode 100644 panel/styles/Admin.module.css create mode 100644 panel/styles/Button.module.css create mode 100644 panel/styles/CodePreview.module.css create mode 100644 panel/styles/Form.module.css create mode 100644 panel/styles/GlobalVariables.module.css create mode 100644 panel/styles/Loading.module.css create mode 100644 panel/styles/Login.module.css create mode 100644 panel/styles/Modal.module.css create mode 100644 panel/styles/Pagination.module.css create mode 100644 panel/styles/Table.module.css create mode 100644 panel/styles/Utilities.module.css create mode 100644 panel/types/css.d.ts create mode 100644 panel/types/svg.d.ts create mode 100644 panel/ui/Button.tsx create mode 100644 panel/ui/CodePreview.tsx create mode 100644 panel/ui/EditableCodePreview.tsx create mode 100644 panel/ui/Modal.tsx create mode 100644 panel/ui/Pagination.tsx create mode 100644 panel/ui/TextPreview.tsx create mode 100644 panel/utils/auth.ts create mode 100644 panel/utils/date.ts diff --git a/.gitignore b/.gitignore index 3b114c8c..7b7344b4 100644 --- a/.gitignore +++ b/.gitignore @@ -164,3 +164,8 @@ views.json .cursor node_modules/ +panel/graphql/generated/ +panel/types.gen.ts + +.cursorrules +.cursor/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fdf0ca9..a437f43f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,159 @@ # Changelog +## [0.5.8] - 2025-06-30 + +### Улучшения интерфейса публикаций + +- **НОВОЕ**: Статусы публикаций иконками: + - **Опубликовано**: ✅ (зелёный бэдж) - быстрая визуальная идентификация опубликованных статей + - **Черновик**: 📝 (жёлтый бэдж) - чёткое обозначение незавершённых публикаций + - **Удалено**: 🗑️ (красный бэдж) - явное указание на удалённые материалы + - **Компактный дизайн**: Статус-бэджи 32×32px с центрированными иконками для экономии места + - **Tooltip поддержка**: При наведении показывается текстовое описание статуса для полной ясности + +- **УЛУЧШЕНО**: Выравнивание элементов управления: + - **Логичная группировка**: Поиск и элементы управления размещены в одной строке слева направо + - **Убран разброс**: Элементы больше не разбросаны по разным концам экрана (`justify-content: space-between`) + - **Удалён фильтр статуса**: Упрощён интерфейс за счёт удаления избыточного селектора фильтрации + - **Flex gap**: Равномерные отступы 1.5rem между элементами управления + - **Responsive дизайн**: Элементы корректно переносятся на мобильных устройствах (`flex-wrap`) + +- **Архитектурные улучшения**: + - **Функция getShoutStatusTitle()**: Отдельная функция для получения текстового описания статуса + - **Обновлённые CSS классы**: Модернизированные стили для status-badge с flexbox центрированием + - **Лучшая семантика**: Title атрибуты для accessibility и пользовательского опыта + +### Сортировка топиков и управление сообществами + +- **НОВОЕ**: Сортировка топиков в админ-панели: + - **Выпадающий селектор**: Выбор между сортировкой по ID и названию + - **Направление сортировки**: По возрастанию/убыванию с интуитивными стрелочками ↑↓ + - **Умная русская сортировка**: Использование `localeCompare('ru')` для корректной сортировки русских названий + - **Рекурсивная сортировка**: Дочерние топики также сортируются по выбранному критерию + - **Реактивность**: Автоматическое пересортирование при изменении параметров + - **Сохранение иерархии**: Древовидная структура сохраняется при любом типе сортировки + +- **НОВОЕ**: Полноценное управление сообществами: + - **Новая вкладка "Сообщества"**: Отдельная секция в админ-панели для управления сообществами + - **Подробная таблица**: ID, название, slug, описание, создатель, статистика (публикации/подписчики/авторы), дата создания + - **Клик для редактирования**: Нажатие на строку открывает модалку редактирования сообщества + - **Удаление с подтверждением**: Тонкая кнопка "×" для удаления с двойным подтверждением + - **Полная CRUD функциональность**: Создание, редактирование, удаление сообществ + - **Исправлена проблема с загрузкой**: Добавлен relationship для `created_by` в ORM модели Community + - **Резолвер поля created_by**: Корректное получение информации о создателе сообщества + +### Улучшенное управление пользователями + +- **КАРДИНАЛЬНО НОВАЯ модалка редактирования пользователя**: + - **Красивый современный дизайн**: Карточки для ролей, секционное разделение, современная типографика + - **Полное редактирование профиля**: Email, имя, slug, роли (не только роли как раньше) + - **Умная валидация**: Проверка email, обязательных полей, уникальности slug + - **Информационная панель**: Отображение ID, даты регистрации, последней активности + - **Интерактивные карточки ролей**: Описание каждой роли с иконками состояния + - **Расширенная GraphQL схема**: `AdminUserUpdateInput` теперь поддерживает email, name, slug + - **Улучшенный резолвер**: `adminUpdateUser` обрабатывает профильные поля с проверкой уникальности + - **Реальная валидация**: Проверка email и slug на уникальность в базе данных + - **Детальное логирование**: Подробные сообщения об изменениях в профиле и ролях + +- **ТЕХНИЧЕСКАЯ АРХИТЕКТУРА**: + - **Переименование компонента**: `RolesModal` → `UserEditModal` для отражения расширенного функционала + - **Новые CSS стили**: Добавлены стили для форм, карточек ролей, валидации в `Form.module.css` + - **Обновленный API интерфейс**: `onSave` теперь принимает полный объект пользователя вместо только ролей + - **Реактивная форма**: Автоочистка ошибок при изменении полей, сброс состояния при открытии + +### Полноценное редактирование топиков в админ-панели + +- **НОВОЕ**: Редактирование всех полей топиков: + - **Колонка ID**: Отображение идентификаторов топиков в таблице для точной идентификации + - **Редактирование названия**: Изменение `title` прямо в модальном окне + - **Простой HTML редактор**: Обычный `contenteditable` div вместо сложного редактора кода + - **Управление сообществом**: Изменение `community` ID с валидацией + - **Управление иерархией**: Редактирование `parent_ids` (список родительских топиков через запятую) + - **Картинки**: Редактирование URL картинки (`pic`) + +- **Улучшения UI/UX**: + - **Клик по строке для редактирования**: Убрана кнопка "Редактировать", модалка открывается кликом на любом месте строки + - **Ненавязчивый крестик удаления**: Простая кнопка "×" серого цвета, которая становится красной при наведении + - **Колонка "Родители"**: Отображение списка parent_ids в основной таблице + - **Простой HTML редактор**: Обычный contenteditable div с моноширинным шрифтом и placeholder + - **Подтверждение удаления**: Модальное окно при клике на крестик + +- **Архитектурные улучшения**: + - **TopicInput расширен**: Добавлены поля `community` и `parent_ids` в GraphQL схему + - **Новые мутации**: `UPDATE_TOPIC_MUTATION` и `DELETE_TOPIC_MUTATION` в mutations.ts + - **TopicEditModal**: Переиспользуемый компонент с простым интерфейсом + - **Парсинг parent_ids**: Автоматическое преобразование строки "1, 5, 12" в массив чисел + - **Синхронизация данных**: createEffect для синхронизации формы с выбранным топиком + +- **Технические детали**: + - **Кликабельные строки**: Hover эффект и cursor pointer для лучшего UX + - **Prevent event bubbling**: Правильная обработка клика на крестике без открытия модалки + - **CSS стили**: Стили для hover эффектов крестика и placeholder в contenteditable + - **Валидация**: Обязательное поле `slug`, проверка числовых полей + - **Обработка ошибок**: Корректное отображение ошибок GraphQL + - **Автообновление**: Перезагрузка списка топиков после успешного сохранения + +### Рефакторинг админ-панели + +- **ИСПРАВЛЕНО**: Переключение табов в админ-панели: + - **Проблема**: Роутинг не работал корректно - табы не переключались при клике + - **Решение**: Заменен `useLocation` на `useParams` для корректного получения активной вкладки + - **Улучшения**: Исправлена логика навигации с `replace: true` для редиректа на `/admin/authors` + - **Результат**: Теперь переключение между табами работает плавно и корректно + +- **НОВОЕ**: Управление топиками в админ-панели: + - **Иерархическое отображение**: Темы показываются в виде дерева с отступами и символами `└─` + - **Удаление в один клик**: Кнопка удаления с модальным окном подтверждения + - **Информативная таблица**: Название, slug, описание, сообщество, действия + - **Предупреждения**: Информация о том что дочерние топики также будут удалены + - **Автообновление**: Список перезагружается после успешного удаления + +### Codegen рефакторинг + +- **GraphQL Codegen**: Настроена автоматическая генерация TypeScript типов: + - **Файл конфигурации**: `codegen.ts` с настройками для client-side генерации + - **Автоматические типы**: Генерация из GraphQL схемы в `panel/graphql/generated/` + - **Структура**: Разделение на queries, mutations и index файлы + - **TypeScript интеграция**: Полная типизация для админ-панели + +- **Архитектурные улучшения**: + - **Модульная структура**: Разделение GraphQL операций по назначению + - **Type safety**: Строгая типизация для всех GraphQL операций + - **Developer Experience**: Автокомплит и проверка типов в IDE + +### Улучшения системы кеширования + +- **НОВОЕ**: Функция `invalidate_topic_followers_cache()` в модуле cache: + - **Централизованная логика**: Все операции по инвалидации кешей подписчиков в одном месте + - **Комплексная обработка**: Инвалидация кешей как самого топика, так и всех его подписчиков + - **Правильная последовательность**: Получение подписчиков ДО удаления данных из БД + - **Подробное логирование**: Отслеживание всех операций инвалидации для отладки + +- **Исправлена логика удаления топиков**: + - **Проблема**: При удалении топика не обновлялись счетчики подписок у всех подписчиков + - **Решение**: Добавлена инвалидация персональных кешей для каждого подписчика: + - `author:follows-topics:{follower_id}` - список подписок на топики + - `author:followers:{follower_id}` - счетчики подписчиков + - `author:stat:{follower_id}` - общая статистика автора + - **Результат**: Система поддерживает консистентность кешей при удалении топиков + +- **Архитектурные улучшения**: + - **Разделение ответственности**: Cache модуль отвечает за кеширование, резолверы за бизнес-логику + - **Переиспользуемость**: Функцию можно использовать в других операциях с топиками + - **Тестируемость**: Логику кеширования легко мокать и тестировать отдельно + +### GraphQL Schema + +- **Новые операции**: + - `delete_topic_by_id(id: Int!)` - удаление топика по ID для админ-панели + - Обновленный `get_topics_all` для корректной типизации + +### Исправления резолверов + +- **Использование существующей схемы**: Приведение кода в соответствие с truth source схемой GraphQL +- **Упрощение**: Убраны дублирующиеся резолверы, используются существующие `get_topics_all` +- **Чистота кода**: Удалена дублированная логика инвалидации кешей + ## [0.5.7] - 2025-06-28 ### Новая функциональность админ-панели @@ -466,7 +620,7 @@ - Modified `load_reactions_by` to include deleted reactions when `include_deleted=true` for proper comment tree building - Fixed featured/unfeatured logic in reaction processing: - Dislike reactions now properly take precedence over likes - - Featured status now requires more than 4 likes from users with featured articles + - Featured status now requires more than 4 likes from authors with featured articles - Removed unnecessary filters for deleted reactions since rating reactions are physically deleted - Author's featured status now based on having non-deleted articles with featured_at diff --git a/auth/decorators.py b/auth/decorators.py index 1f58d209..a929f653 100644 --- a/auth/decorators.py +++ b/auth/decorators.py @@ -380,49 +380,96 @@ def permission_required(resource: str, operation: str, func: Callable) -> Callab def login_accepted(func: Callable) -> Callable: """ - Декоратор для резолверов, которые могут работать как с авторизованными, - так и с неавторизованными пользователями. - - Добавляет информацию о пользователе в контекст, если пользователь авторизован. + Декоратор для проверки аутентификации пользователя. Args: - func: Декорируемая функция + func: функция-резолвер для декорирования + + Returns: + Callable: обернутая функция """ @wraps(func) async def wrap(parent: Any, info: GraphQLResolveInfo, *args: Any, **kwargs: Any) -> Any: try: - # Пробуем проверить авторизацию, но не выбрасываем исключение, если пользователь не авторизован - try: - await validate_graphql_context(info) - except GraphQLError: - # Игнорируем ошибку авторизации - pass - - # Получаем объект авторизации - auth = None - if hasattr(info.context["request"], "scope") and "auth" in info.context["request"].scope: - auth = info.context["request"].scope.get("auth") - - if auth and getattr(auth, "logged_in", False): - # Если пользователь авторизован, добавляем информацию о нем в контекст - with local_session() as session: - try: - author = session.query(Author).filter(Author.id == auth.author_id).one() - info.context["author"] = author.dict() - logger.debug(f"[login_accepted] Пользователь авторизован: {author.id}") - except exc.NoResultFound: - logger.warning(f"[login_accepted] Пользователь с ID {auth.author_id} не найден в базе данных") - info.context["author"] = None - else: - # Если пользователь не авторизован, устанавливаем пустые значения - info.context["author"] = None - logger.debug("[login_accepted] Пользователь не авторизован") - + await validate_graphql_context(info) return await func(parent, info, *args, **kwargs) - except Exception as e: - if not isinstance(e, GraphQLError): - logger.error(f"[login_accepted] Ошибка: {e}") + except GraphQLError: + # Пробрасываем ошибки авторизации далее raise + except Exception as e: + logger.error(f"[decorators] Unexpected error in login_accepted: {e}") + msg = "Internal server error" + raise GraphQLError(msg) from e + + return wrap + + +def editor_or_admin_required(func: Callable) -> Callable: + """ + Декоратор для проверки, что пользователь имеет роль 'editor' или 'admin'. + + Args: + func: функция-резолвер для декорирования + + Returns: + Callable: обернутая функция + """ + + @wraps(func) + async def wrap(parent: Any, info: GraphQLResolveInfo, *args: Any, **kwargs: Any) -> Any: + try: + # Сначала проверяем авторизацию + await validate_graphql_context(info) + + # Получаем информацию о пользователе + request = info.context.get("request") + author_id = None + + # Пробуем получить author_id из разных источников + if hasattr(request, "auth") and request.auth and hasattr(request.auth, "author_id"): + author_id = request.auth.author_id + elif hasattr(request, "scope") and "auth" in request.scope: + auth_info = request.scope.get("auth", {}) + if isinstance(auth_info, dict): + author_id = auth_info.get("author_id") + elif hasattr(auth_info, "author_id"): + author_id = auth_info.author_id + + if not author_id: + logger.warning("[decorators] Не удалось получить author_id для проверки ролей") + raise GraphQLError("Ошибка авторизации: не удалось определить пользователя") + + # Проверяем роли пользователя + with local_session() as session: + author = session.query(Author).filter(Author.id == author_id).first() + if not author: + logger.warning(f"[decorators] Автор с ID {author_id} не найден") + raise GraphQLError("Пользователь не найден") + + # Проверяем email админа + if author.email in ADMIN_EMAILS: + logger.debug(f"[decorators] Пользователь {author.email} является админом по email") + return await func(parent, info, *args, **kwargs) + + # Получаем список ролей пользователя + user_roles = [role.id for role in author.roles] if author.roles else [] + logger.debug(f"[decorators] Роли пользователя {author_id}: {user_roles}") + + # Проверяем наличие роли admin или editor + if "admin" in user_roles or "editor" in user_roles: + logger.debug(f"[decorators] Пользователь {author_id} имеет разрешение (роли: {user_roles})") + return await func(parent, info, *args, **kwargs) + + # Если нет нужных ролей + logger.warning(f"[decorators] Пользователю {author_id} отказано в доступе. Роли: {user_roles}") + raise GraphQLError("Доступ запрещен. Требуется роль редактора или администратора.") + + except GraphQLError: + # Пробрасываем ошибки авторизации далее + raise + except Exception as e: + logger.error(f"[decorators] Неожиданная ошибка в editor_or_admin_required: {e}") + raise GraphQLError("Внутренняя ошибка сервера") from e return wrap diff --git a/auth/oauth.py b/auth/oauth.py index 38f5af56..f38ffeaa 100644 --- a/auth/oauth.py +++ b/auth/oauth.py @@ -200,14 +200,14 @@ async def _fetch_facebook_profile(client: Any, token: Any) -> dict: async def _fetch_x_profile(client: Any, token: Any) -> dict: """Получает профиль из X (Twitter) API""" - profile = await client.get("users/me?user.fields=id,name,username,profile_image_url", token=token) + profile = await client.get("authors/me?user.fields=id,name,username,profile_image_url", token=token) profile_data = profile.json() return PROVIDER_HANDLERS["x"](token, profile_data) async def _fetch_vk_profile(client: Any, token: Any) -> dict: """Получает профиль из VK API""" - profile = await client.get("users.get?fields=photo_400_orig,contacts&v=5.131", token=token) + profile = await client.get("authors.get?fields=photo_400_orig,contacts&v=5.131", token=token) profile_data = profile.json() if profile_data.get("response"): user_data = profile_data["response"][0] diff --git a/biome.json b/biome.json index be37bc30..ae00ff83 100644 --- a/biome.json +++ b/biome.json @@ -1,8 +1,19 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "$schema": "https://biomejs.dev/schemas/2.0.6/schema.json", "files": { - "include": ["*.tsx", "*.ts", "*.js", "*.json"], - "ignore": ["./dist", "./node_modules", ".husky", "docs", "gen", "*.gen.ts", "*.d.ts"] + "includes": [ + "**/*.tsx", + "**/*.ts", + "**/*.js", + "**/*.json", + "!dist", + "!node_modules", + "!**/.husky", + "!**/docs", + "!**/gen", + "!**/*.gen.ts", + "!**/*.d.ts" + ] }, "vcs": { "enabled": true, @@ -10,16 +21,13 @@ "useIgnoreFile": true, "clientKind": "git" }, - "organizeImports": { - "enabled": true, - "ignore": ["./gen"] - }, + "assist": { "actions": { "source": { "organizeImports": "on" } } }, "formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, "lineWidth": 108, - "ignore": ["./src/graphql/schema", "./gen"] + "includes": ["**", "!src/graphql/schema", "!gen", "!panel/graphql/generated"] }, "javascript": { "formatter": { @@ -33,11 +41,11 @@ }, "linter": { "enabled": true, - "ignore": ["*.scss", "*.md", ".DS_Store", "*.svg", "*.d.ts"], + "includes": ["**", "!**/*.scss", "!**/*.md", "!**/.DS_Store", "!**/*.svg", "!**/*.d.ts"], "rules": { - "all": true, "complexity": { "noForEach": "off", + "noUselessFragments": "off", "useOptionalChain": "warn", "useLiteralKeys": "off", "noExcessiveCognitiveComplexity": "off", @@ -46,10 +54,7 @@ "correctness": { "useHookAtTopLevel": "off", "useImportExtensions": "off", - "noUndeclaredDependencies": "off", - "noNodejsModules": { - "level": "off" - } + "noUndeclaredDependencies": "off" }, "a11y": { "useHeadingContent": "off", @@ -61,18 +66,16 @@ "useAltText": "off", "useButtonType": "off", "noRedundantAlt": "off", + "noStaticElementInteractions": "off", "noSvgWithoutTitle": "off", "noLabelWithoutControl": "off" }, - "nursery": { - "useImportRestrictions": "off" - }, "performance": { - "noBarrelFile": "off" + "noBarrelFile": "off", + "noNamespaceImport": "warn" }, "style": { "noNonNullAssertion": "off", - "noNamespaceImport": "warn", "noUselessElse": "off", "useBlockStatements": "off", "noImplicitBoolean": "off", @@ -81,12 +84,25 @@ "noDefaultExport": "off", "useFilenamingConvention": "off", "useExplicitLengthCheck": "off", - "useNodejsImportProtocol": "off" + "noParameterAssign": "error", + "useAsConstAssertion": "error", + "useDefaultParameterLast": "error", + "useEnumInitializers": "error", + "useSelfClosingElements": "error", + "useSingleVarDeclarator": "error", + "noUnusedTemplateLiteral": "error", + "useNumberNamespace": "error", + "noInferrableTypes": "error" }, "suspicious": { "noConsole": "off", - "noConsoleLog": "off", - "noAssignInExpressions": "off" + "noAssignInExpressions": "off", + "useAwait": "off", + "noEmptyBlockStatements": "off" + }, + "nursery": { + "noFloatingPromises": "warn", + "noImportCycles": "warn" } } } diff --git a/cache/cache.py b/cache/cache.py index 5597990c..060d346d 100644 --- a/cache/cache.py +++ b/cache/cache.py @@ -462,11 +462,8 @@ async def cache_related_entities(shout: Shout) -> None: """ Кэширует все связанные с публикацией сущности (авторов и темы) """ - tasks = [] - for author in shout.authors: - tasks.append(cache_by_id(Author, author.id, cache_author)) - for topic in shout.topics: - tasks.append(cache_by_id(Topic, topic.id, cache_topic)) + tasks = [cache_by_id(Author, author.id, cache_author) for author in shout.authors] + tasks.extend(cache_by_id(Topic, topic.id, cache_topic) for topic in shout.topics) await asyncio.gather(*tasks) @@ -846,22 +843,85 @@ async def invalidate_author_cache(author_id: Union[int, str]) -> None: async def clear_all_cache() -> None: - """Очищает весь кеш (использовать осторожно)""" + """ + Очищает весь кэш Redis (используйте с осторожностью!) + + Warning: + Эта функция удаляет ВСЕ данные из Redis! + Используйте только в тестовой среде или при критической необходимости. + """ try: - # Get all cache keys - topic_keys = await redis.keys("topic:*") - author_keys = await redis.keys("author:*") - search_keys = await redis.keys("search:*") - follows_keys = await redis.keys("follows:*") + await redis.execute("FLUSHDB") + logger.info("Весь кэш очищен") + except Exception as e: + logger.error(f"Ошибка при очистке кэша: {e}") - all_keys = topic_keys + author_keys + search_keys + follows_keys - if all_keys: - for key in all_keys: - await redis.delete(key) - logger.info(f"Cleared {len(all_keys)} cache entries") - else: - logger.info("No cache entries to clear") +async def invalidate_topic_followers_cache(topic_id: int) -> None: + """ + Инвалидирует кеши подписчиков при удалении топика. + + Эта функция: + 1. Получает список всех подписчиков топика + 2. Инвалидирует персональные кеши подписок для каждого подписчика + 3. Инвалидирует кеши самого топика + 4. Логирует процесс для отладки + + Args: + topic_id: ID топика для которого нужно инвалидировать кеши подписчиков + """ + try: + logger.debug(f"Инвалидация кешей подписчиков для топика {topic_id}") + + # Получаем список всех подписчиков топика из БД + with local_session() as session: + followers_query = session.query(TopicFollower.follower).filter(TopicFollower.topic == topic_id) + follower_ids = [row[0] for row in followers_query.all()] + + logger.debug(f"Найдено {len(follower_ids)} подписчиков топика {topic_id}") + + # Инвалидируем кеши подписок для всех подписчиков + for follower_id in follower_ids: + cache_keys_to_delete = [ + f"author:follows-topics:{follower_id}", # Список топиков на которые подписан автор + f"author:followers:{follower_id}", # Счетчик подписчиков автора + f"author:stat:{follower_id}", # Общая статистика автора + f"author:id:{follower_id}", # Кешированные данные автора + ] + + for cache_key in cache_keys_to_delete: + try: + await redis.execute("DEL", cache_key) + logger.debug(f"Удален кеш: {cache_key}") + except Exception as e: + logger.error(f"Ошибка при удалении кеша {cache_key}: {e}") + + # Инвалидируем кеши самого топика + topic_cache_keys = [ + f"topic:followers:{topic_id}", # Список подписчиков топика + f"topic:id:{topic_id}", # Данные топика по ID + f"topic:authors:{topic_id}", # Авторы топика + f"topic_shouts_{topic_id}", # Публикации топика (legacy format) + ] + + for cache_key in topic_cache_keys: + try: + await redis.execute("DEL", cache_key) + logger.debug(f"Удален кеш топика: {cache_key}") + except Exception as e: + logger.error(f"Ошибка при удалении кеша топика {cache_key}: {e}") + + # Также ищем и удаляем коллекционные кеши, содержащие данные об этом топике + try: + collection_keys = await redis.execute("KEYS", "topics:stats:*") + if collection_keys: + await redis.execute("DEL", *collection_keys) + logger.debug(f"Удалено {len(collection_keys)} коллекционных ключей тем") + except Exception as e: + logger.error(f"Ошибка при удалении коллекционных кешей: {e}") + + logger.info(f"Успешно инвалидированы кеши для топика {topic_id} и {len(follower_ids)} подписчиков") except Exception as e: - logger.error(f"Failed to clear cache: {e}") + logger.error(f"Ошибка при инвалидации кешей подписчиков топика {topic_id}: {e}") + raise diff --git a/codegen.ts b/codegen.ts new file mode 100644 index 00000000..cc5355c7 --- /dev/null +++ b/codegen.ts @@ -0,0 +1,38 @@ +import type { CodegenConfig } from '@graphql-codegen/cli' + +const config: CodegenConfig = { + overwrite: true, + schema: [ + 'schema/type.graphql', + 'schema/enum.graphql', + 'schema/input.graphql', + 'schema/mutation.graphql', + 'schema/query.graphql', + 'schema/admin.graphql' + ], + documents: ['panel/**/*.{ts,tsx}'], + generates: { + './panel/graphql/generated/': { + preset: 'client', + plugins: [], + presetConfig: { + gqlTagName: 'gql', + fragmentMasking: false + } + }, + './panel/graphql/generated/schema.ts': { + plugins: ['typescript', 'typescript-resolvers'], + config: { + contextType: '../types#GraphQLContext', + enumsAsTypes: true, + useIndexSignature: true, + scalars: { + DateTime: 'string', + JSON: '{ [key: string]: any }' + } + } + } + } +} + +export default config diff --git a/docs/README.md b/docs/README.md index fa870e38..15f64bcf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,6 +32,14 @@ python dev.py ### Администрирование - **Админ-панель**: Управление пользователями, ролями, переменными среды - **Управление публикациями**: Просмотр, поиск, фильтрация по статусу (опубликованные/черновики/удаленные) +- **Управление топиками**: Упрощенное редактирование топиков с иерархическим отображением + - **Клик по строке**: Модалка редактирования открывается при клике на строку таблицы + - **Ненавязчивый крестик**: Серая кнопка "×" для удаления, краснеет при hover + - **Простой HTML редактор**: Обычный contenteditable div с моноширинным шрифтом + - **Редактируемые поля**: ID (просмотр), название, slug, описание, сообщество, родители + - **Дерево топиков**: Визуализация родительско-дочерних связей с отступами и символами `└─` + - **Безопасное удаление**: Предупреждения о каскадном удалении дочерних топиков + - **Автообновление**: Рефреш списка после операций с корректной инвалидацией кешей - **Просмотр данных**: Body, media, авторы, темы с удобной навигацией - **DRY принцип**: Переиспользование существующих резолверов из reader.py и editor.py diff --git a/docs/features.md b/docs/features.md index d22e286a..d30692cf 100644 --- a/docs/features.md +++ b/docs/features.md @@ -1,3 +1,48 @@ +## Админ-панель + +- **Управление пользователями**: Просмотр, поиск, назначение ролей (user/moderator/admin) +- **Управление публикациями**: Таблица со всеми публикациями, фильтрация по статусу, превью контента +- **Управление топиками**: Полноценное редактирование топиков в админ-панели + - **Иерархическое отображение**: Темы показываются в виде дерева с отступами и символами `└─` для дочерних элементов + - **Колонки таблицы**: ID, название, slug, описание, сообщество, родители, действия + - **Простой интерфейс редактирования**: + - **Клик по строке**: Модалка редактирования открывается при клике на любом месте строки таблицы + - **Ненавязчивый крестик**: Кнопка удаления в виде серого "×", краснеет при hover + - **Простой HTML редактор**: Обычный contenteditable div с моноширинным шрифтом вместо сложного редактора + - **Редактируемые поля**: + - **ID**: Отображается для идентификации (поле только для чтения) + - **Название и slug**: Текстовые поля для основной информации + - **Описание**: Простой HTML редактор с placeholder + - **Картинка**: URL изображения топика + - **Сообщество**: ID сообщества с числовой валидацией + - **Родители**: Список parent_ids через запятую с автоматическим парсингом + - **Безопасное удаление**: Модальное окно подтверждения при клике на крестик + - **Корректная инвалидация кешей**: Автоматическое обновление счетчиков подписок у всех подписчиков + - **GraphQL интеграция**: Использование мутаций `UPDATE_TOPIC_MUTATION` и `DELETE_TOPIC_MUTATION` +- **Управление переменными среды**: Настройка конфигурации приложения +- **TypeScript интеграция**: Полная типизация с автогенерацией типов из GraphQL схемы +- **Responsive дизайн**: Адаптивность для разных размеров экранов + +## Codegen интеграция + +- **Автоматическая генерация типов**: TypeScript типы генерируются из GraphQL схемы +- **Файл конфигурации**: `codegen.ts` с настройками для client-side генерации +- **Структура проекта**: Разделение на queries, mutations и index файлы в `panel/graphql/generated/` +- **Type safety**: Строгая типизация для всех GraphQL операций в админ-панели +- **Developer Experience**: Автокомплит и проверка типов в IDE + +## Улучшенная система кеширования топиков + +- **Централизованная функция**: `invalidate_topic_followers_cache()` в модуле cache +- **Комплексная инвалидация**: Обработка кешей как самого топика, так и всех его подписчиков +- **Правильная последовательность**: Получение подписчиков ДО удаления данных из БД +- **Инвалидируемые кеши**: + - `author:follows-topics:{follower_id}` - список подписок на топики + - `author:followers:{follower_id}` - счетчики подписчиков + - `author:stat:{follower_id}` - общая статистика автора + - `topic:followers:{topic_id}` - список подписчиков топика +- **Архитектурные принципы**: Разделение ответственности, переиспользуемость, тестируемость + ## Просмотры публикаций - Интеграция с Google Analytics для отслеживания просмотров публикаций diff --git a/docs/follower.md b/docs/follower.md index 06e8d666..7aef9e2c 100644 --- a/docs/follower.md +++ b/docs/follower.md @@ -42,7 +42,7 @@ Unfollow an entity. ### Queries #### get_shout_followers -Get list of users who reacted to a shout. +Get list of authors who reacted to a shout. **Parameters:** - `slug: String` - Shout slug diff --git a/docs/oauth-deployment.md b/docs/oauth-deployment.md index c61df78d..d9f000f3 100644 --- a/docs/oauth-deployment.md +++ b/docs/oauth-deployment.md @@ -34,7 +34,7 @@ JWT_EXPIRATION_HOURS=24 -- Create oauth_links table CREATE TABLE oauth_links ( id SERIAL PRIMARY KEY, - user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + user_id INTEGER NOT NULL REFERENCES authors(id) ON DELETE CASCADE, provider VARCHAR(50) NOT NULL, provider_id VARCHAR(255) NOT NULL, provider_data JSONB, diff --git a/docs/oauth.md b/docs/oauth.md index 29be14c3..3e2911b0 100644 --- a/docs/oauth.md +++ b/docs/oauth.md @@ -295,7 +295,7 @@ async def migrate_oauth_tokens(): refresh_token=author.provider_refresh_token ) - print(f"Migrated OAuth tokens for {len(authors)} users") + print(f"Migrated OAuth tokens for {len(authors)} authors") ``` ## Performance Benefits diff --git a/orm/community.py b/orm/community.py index e0f5ece5..816f8392 100644 --- a/orm/community.py +++ b/orm/community.py @@ -18,7 +18,7 @@ class CommunityRole(enum.Enum): ADMIN = "admin" @classmethod - def as_string_array(cls, roles): + def as_string_array(cls, roles) -> list[str]: return [role.value for role in roles] @classmethod @@ -59,6 +59,7 @@ class Community(BaseModel): private = Column(Boolean, default=False) followers = relationship("Author", secondary="community_follower") + created_by_author = relationship("Author", foreign_keys=[created_by]) @hybrid_property def stat(self): diff --git a/package-lock.json b/package-lock.json index 652c1ad7..cd05c698 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,25 +1,33 @@ { - "name": "admin-panel", - "version": "0.4.22", + "name": "publy-panel", + "version": "0.5.8", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "admin-panel", - "version": "0.4.22", + "name": "publy-panel", + "version": "0.5.8", "dependencies": { - "prismjs": "^1.30.0" + "@solidjs/router": "^0.15.3" }, "devDependencies": { - "@biomejs/biome": "^1.9.4", - "@types/node": "^22.15.0", + "@biomejs/biome": "^2.0.6", + "@graphql-codegen/cli": "^5.0.7", + "@graphql-codegen/client-preset": "^4.8.3", + "@graphql-codegen/typescript": "^4.0.6", + "@graphql-codegen/typescript-operations": "^4.2.0", + "@graphql-codegen/typescript-resolvers": "^4.0.6", + "@types/node": "^24.0.7", "@types/prismjs": "^1.26.5", - "graphql": "^16.8.0", - "solid-js": "^1.9.6", + "graphql": "^16.11.0", + "graphql-tag": "^2.12.6", + "lightningcss": "^1.30.0", + "prismjs": "^1.30.0", + "solid-js": "^1.9.7", "terser": "^5.39.0", - "typescript": "^5.8.0", - "vite": "^6.3.0", - "vite-plugin-solid": "^2.11.0" + "typescript": "^5.8.3", + "vite": "^7.0.0", + "vite-plugin-solid": "^2.11.7" } }, "node_modules/@ampproject/remapping": { @@ -36,6 +44,31 @@ "node": ">=6.0.0" } }, + "node_modules/@ardatan/relay-compiler": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/@ardatan/relay-compiler/-/relay-compiler-12.0.3.tgz", + "integrity": "sha512-mBDFOGvAoVlWaWqs3hm1AciGHSQE1rqFc/liZTyYz/Oek9yZdT5H26pH2zAFuEiTiBVPPyMuqf5VjOFPI2DGsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/runtime": "^7.26.10", + "chalk": "^4.0.0", + "fb-watchman": "^2.0.0", + "immutable": "~3.7.6", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "relay-runtime": "12.0.0", + "signedsource": "^1.0.0" + }, + "bin": { + "relay-compiler": "bin/relay-compiler" + }, + "peerDependencies": { + "graphql": "*" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -213,13 +246,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", + "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.27.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -228,6 +261,22 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-jsx": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", @@ -244,6 +293,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", @@ -279,9 +338,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", + "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", "dev": true, "license": "MIT", "dependencies": { @@ -293,11 +352,10 @@ } }, "node_modules/@biomejs/biome": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", - "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.0.6.tgz", + "integrity": "sha512-RRP+9cdh5qwe2t0gORwXaa27oTOiQRQvrFf49x2PA1tnpsyU7FIHX4ZOFMtBC4QNtyWsN7Dqkf5EDbg4X+9iqA==", "dev": true, - "hasInstallScript": true, "license": "MIT OR Apache-2.0", "bin": { "biome": "bin/biome" @@ -310,20 +368,20 @@ "url": "https://opencollective.com/biome" }, "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "1.9.4", - "@biomejs/cli-darwin-x64": "1.9.4", - "@biomejs/cli-linux-arm64": "1.9.4", - "@biomejs/cli-linux-arm64-musl": "1.9.4", - "@biomejs/cli-linux-x64": "1.9.4", - "@biomejs/cli-linux-x64-musl": "1.9.4", - "@biomejs/cli-win32-arm64": "1.9.4", - "@biomejs/cli-win32-x64": "1.9.4" + "@biomejs/cli-darwin-arm64": "2.0.6", + "@biomejs/cli-darwin-x64": "2.0.6", + "@biomejs/cli-linux-arm64": "2.0.6", + "@biomejs/cli-linux-arm64-musl": "2.0.6", + "@biomejs/cli-linux-x64": "2.0.6", + "@biomejs/cli-linux-x64-musl": "2.0.6", + "@biomejs/cli-win32-arm64": "2.0.6", + "@biomejs/cli-win32-x64": "2.0.6" } }, "node_modules/@biomejs/cli-darwin-arm64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", - "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-AzdiNNjNzsE6LfqWyBvcL29uWoIuZUkndu+wwlXW13EKcBHbbKjNQEZIJKYDc6IL+p7bmWGx3v9ZtcRyIoIz5A==", "cpu": [ "arm64" ], @@ -338,9 +396,9 @@ } }, "node_modules/@biomejs/cli-darwin-x64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", - "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.0.6.tgz", + "integrity": "sha512-wJjjP4E7bO4WJmiQaLnsdXMa516dbtC6542qeRkyJg0MqMXP0fvs4gdsHhZ7p9XWTAmGIjZHFKXdsjBvKGIJJQ==", "cpu": [ "x64" ], @@ -355,9 +413,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", - "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.0.6.tgz", + "integrity": "sha512-ZSVf6TYo5rNMUHIW1tww+rs/krol7U5A1Is/yzWyHVZguuB0lBnIodqyFuwCNqG9aJGyk7xIMS8HG0qGUPz0SA==", "cpu": [ "arm64" ], @@ -372,9 +430,9 @@ } }, "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", - "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.0.6.tgz", + "integrity": "sha512-CVPEMlin3bW49sBqLBg2x016Pws7eUXA27XYDFlEtponD0luYjg2zQaMJ2nOqlkKG9fqzzkamdYxHdMDc2gZFw==", "cpu": [ "arm64" ], @@ -389,9 +447,9 @@ } }, "node_modules/@biomejs/cli-linux-x64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", - "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.0.6.tgz", + "integrity": "sha512-geM1MkHTV1Kh2Cs/Xzot9BOF3WBacihw6bkEmxkz4nSga8B9/hWy5BDiOG3gHDGIBa8WxT0nzsJs2f/hPqQIQw==", "cpu": [ "x64" ], @@ -406,9 +464,9 @@ } }, "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", - "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.0.6.tgz", + "integrity": "sha512-mKHE/e954hR/hSnAcJSjkf4xGqZc/53Kh39HVW1EgO5iFi0JutTN07TSjEMg616julRtfSNJi0KNyxvc30Y4rQ==", "cpu": [ "x64" ], @@ -423,9 +481,9 @@ } }, "node_modules/@biomejs/cli-win32-arm64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", - "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.0.6.tgz", + "integrity": "sha512-290V4oSFoKaprKE1zkYVsDfAdn0An5DowZ+GIABgjoq1ndhvNxkJcpxPsiYtT7slbVe3xmlT0ncdfOsN7KruzA==", "cpu": [ "arm64" ], @@ -440,9 +498,9 @@ } }, "node_modules/@biomejs/cli-win32-x64": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", - "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.0.6.tgz", + "integrity": "sha512-bfM1Bce0d69Ao7pjTjUS+AWSZ02+5UHdiAP85Th8e9yV5xzw6JrHXbL5YWlcEKQ84FIZMdDc7ncuti1wd2sdbw==", "cpu": [ "x64" ], @@ -456,6 +514,50 @@ "node": ">=14.21.3" } }, + "node_modules/@envelop/core": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@envelop/core/-/core-5.3.0.tgz", + "integrity": "sha512-xvUkOWXI8JsG2OOnqiI2tOkEc52wbmIqWORr7yGc8B8E53Oh1MMGGGck4mbR80s25LnHVzfNIiIlNkuDgZRuuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@envelop/instrumentation": "^1.0.0", + "@envelop/types": "^5.2.1", + "@whatwg-node/promise-helpers": "^1.2.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@envelop/instrumentation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@envelop/instrumentation/-/instrumentation-1.0.0.tgz", + "integrity": "sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/promise-helpers": "^1.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@envelop/types": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@envelop/types/-/types-5.2.1.tgz", + "integrity": "sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/promise-helpers": "^1.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", @@ -881,6 +983,1051 @@ "node": ">=18" } }, + "node_modules/@fastify/busboy": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", + "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@graphql-codegen/add": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz", + "integrity": "sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/add/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/cli": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.7.tgz", + "integrity": "sha512-h/sxYvSaWtxZxo8GtaA8SvcHTyViaaPd7dweF/hmRDpaQU1o3iU3EZxlcJ+oLTunU0tSMFsnrIXm/mhXxI11Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/types": "^7.18.13", + "@graphql-codegen/client-preset": "^4.8.2", + "@graphql-codegen/core": "^4.0.2", + "@graphql-codegen/plugin-helpers": "^5.1.1", + "@graphql-tools/apollo-engine-loader": "^8.0.0", + "@graphql-tools/code-file-loader": "^8.0.0", + "@graphql-tools/git-loader": "^8.0.0", + "@graphql-tools/github-loader": "^8.0.0", + "@graphql-tools/graphql-file-loader": "^8.0.0", + "@graphql-tools/json-file-loader": "^8.0.0", + "@graphql-tools/load": "^8.1.0", + "@graphql-tools/prisma-loader": "^8.0.0", + "@graphql-tools/url-loader": "^8.0.0", + "@graphql-tools/utils": "^10.0.0", + "@whatwg-node/fetch": "^0.10.0", + "chalk": "^4.1.0", + "cosmiconfig": "^8.1.3", + "debounce": "^1.2.0", + "detect-indent": "^6.0.0", + "graphql-config": "^5.1.1", + "inquirer": "^8.0.0", + "is-glob": "^4.0.1", + "jiti": "^1.17.1", + "json-to-pretty-yaml": "^1.2.2", + "listr2": "^4.0.5", + "log-symbols": "^4.0.0", + "micromatch": "^4.0.5", + "shell-quote": "^1.7.3", + "string-env-interpolation": "^1.0.1", + "ts-log": "^2.2.3", + "tslib": "^2.4.0", + "yaml": "^2.3.1", + "yargs": "^17.0.0" + }, + "bin": { + "gql-gen": "cjs/bin.js", + "graphql-code-generator": "cjs/bin.js", + "graphql-codegen": "cjs/bin.js", + "graphql-codegen-esm": "esm/bin.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@parcel/watcher": "^2.1.0", + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "@parcel/watcher": { + "optional": true + } + } + }, + "node_modules/@graphql-codegen/cli/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@graphql-codegen/cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@graphql-codegen/client-preset": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.8.3.tgz", + "integrity": "sha512-QpEsPSO9fnRxA6Z66AmBuGcwHjZ6dYSxYo5ycMlYgSPzAbyG8gn/kWljofjJfWqSY+T/lRn+r8IXTH14ml24vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7", + "@graphql-codegen/add": "^5.0.3", + "@graphql-codegen/gql-tag-operations": "4.0.17", + "@graphql-codegen/plugin-helpers": "^5.1.1", + "@graphql-codegen/typed-document-node": "^5.1.2", + "@graphql-codegen/typescript": "^4.1.6", + "@graphql-codegen/typescript-operations": "^4.6.1", + "@graphql-codegen/visitor-plugin-common": "^5.8.0", + "@graphql-tools/documents": "^1.0.0", + "@graphql-tools/utils": "^10.0.0", + "@graphql-typed-document-node/core": "3.2.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "graphql-sock": "^1.0.0" + }, + "peerDependenciesMeta": { + "graphql-sock": { + "optional": true + } + } + }, + "node_modules/@graphql-codegen/client-preset/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/core": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz", + "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "@graphql-tools/schema": "^10.0.0", + "@graphql-tools/utils": "^10.0.0", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/core/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/gql-tag-operations": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.17.tgz", + "integrity": "sha512-2pnvPdIG6W9OuxkrEZ6hvZd142+O3B13lvhrZ48yyEBh2ujtmKokw0eTwDHtlXUqjVS0I3q7+HB2y12G/m69CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/visitor-plugin-common": "5.8.0", + "@graphql-tools/utils": "^10.0.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/gql-tag-operations/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/plugin-helpers": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.1.1.tgz", + "integrity": "sha512-28GHODK2HY1NhdyRcPP3sCz0Kqxyfiz7boIZ8qIxFYmpLYnlDgiYok5fhFLVSZihyOpCs4Fa37gVHf/Q4I2FEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.0.0", + "change-case-all": "1.0.15", + "common-tags": "1.8.2", + "import-from": "4.0.0", + "lodash": "~4.17.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/plugin-helpers/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/schema-ast": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.1.0.tgz", + "integrity": "sha512-kZVn0z+th9SvqxfKYgztA6PM7mhnSZaj4fiuBWvMTqA+QqQ9BBed6Pz41KuD/jr0gJtnlr2A4++/0VlpVbCTmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "@graphql-tools/utils": "^10.0.0", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/schema-ast/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/typed-document-node": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.1.2.tgz", + "integrity": "sha512-jaxfViDqFRbNQmfKwUY8hDyjnLTw2Z7DhGutxoOiiAI0gE/LfPe0LYaVFKVmVOOD7M3bWxoWfu4slrkbWbUbEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/visitor-plugin-common": "5.8.0", + "auto-bind": "~4.0.0", + "change-case-all": "1.0.15", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/typed-document-node/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/typescript": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.1.6.tgz", + "integrity": "sha512-vpw3sfwf9A7S+kIUjyFxuvrywGxd4lmwmyYnnDVjVE4kSQ6Td3DpqaPTy8aNQ6O96vFoi/bxbZS2BW49PwSUUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/schema-ast": "^4.0.2", + "@graphql-codegen/visitor-plugin-common": "5.8.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/typescript-operations": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.6.1.tgz", + "integrity": "sha512-k92laxhih7s0WZ8j5WMIbgKwhe64C0As6x+PdcvgZFMudDJ7rPJ/hFqJ9DCRxNjXoHmSjnr6VUuQZq4lT1RzCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/typescript": "^4.1.6", + "@graphql-codegen/visitor-plugin-common": "5.8.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "graphql-sock": "^1.0.0" + }, + "peerDependenciesMeta": { + "graphql-sock": { + "optional": true + } + } + }, + "node_modules/@graphql-codegen/typescript-operations/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/typescript-resolvers": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-4.5.1.tgz", + "integrity": "sha512-1Z9xyqcrM+EiuuwpgCGFz3IxlKqn+nS4mRpm81zWW9EHmUyiz1LkinIc+lQ6Ku+F2KyTbLkXUanE970wvdQLmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-codegen/typescript": "^4.1.6", + "@graphql-codegen/visitor-plugin-common": "5.8.0", + "@graphql-tools/utils": "^10.0.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", + "graphql-sock": "^1.0.0" + }, + "peerDependenciesMeta": { + "graphql-sock": { + "optional": true + } + } + }, + "node_modules/@graphql-codegen/typescript-resolvers/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/typescript/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-codegen/visitor-plugin-common": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.8.0.tgz", + "integrity": "sha512-lC1E1Kmuzi3WZUlYlqB4fP6+CvbKH9J+haU1iWmgsBx5/sO2ROeXJG4Dmt8gP03bI2BwjiwV5WxCEMlyeuzLnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.1.0", + "@graphql-tools/optimize": "^2.0.0", + "@graphql-tools/relay-operation-optimizer": "^7.0.0", + "@graphql-tools/utils": "^10.0.0", + "auto-bind": "~4.0.0", + "change-case-all": "1.0.15", + "dependency-graph": "^0.11.0", + "graphql-tag": "^2.11.0", + "parse-filepath": "^1.0.2", + "tslib": "~2.6.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-codegen/visitor-plugin-common/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@graphql-hive/signal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@graphql-hive/signal/-/signal-1.0.0.tgz", + "integrity": "sha512-RiwLMc89lTjvyLEivZ/qxAC5nBHoS2CtsWFSOsN35sxG9zoo5Z+JsFHM8MlvmO9yt+MJNIyC5MLE1rsbOphlag==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@graphql-tools/apollo-engine-loader": { + "version": "8.0.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.20.tgz", + "integrity": "sha512-m5k9nXSyjq31yNsEqDXLyykEjjn3K3Mo73oOKI+Xjy8cpnsgbT4myeUJIYYQdLrp7fr9Y9p7ZgwT5YcnwmnAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.6", + "@whatwg-node/fetch": "^0.10.0", + "sync-fetch": "0.6.0-2", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/batch-execute": { + "version": "9.0.17", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-9.0.17.tgz", + "integrity": "sha512-i7BqBkUP2+ex8zrQrCQTEt6nYHQmIey9qg7CMRRa1hXCY2X8ZCVjxsvbsi7gOLwyI/R3NHxSRDxmzZevE2cPLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.1", + "@whatwg-node/promise-helpers": "^1.3.0", + "dataloader": "^2.2.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/code-file-loader": { + "version": "8.1.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.1.20.tgz", + "integrity": "sha512-GzIbjjWJIc04KWnEr8VKuPe0FA2vDTlkaeub5p4lLimljnJ6C0QSkOyCUnFmsB9jetQcHm0Wfmn/akMnFUG+wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/graphql-tag-pluck": "8.3.19", + "@graphql-tools/utils": "^10.8.6", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/delegate": { + "version": "10.2.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.2.20.tgz", + "integrity": "sha512-vURrChtc3zPyD4XZv7eZj43mIkvuJH8IDDYy7q/AL10N4AJN0dKplWOUA9HSNPSPe3+5dnIUeTno8PX0tV99QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/batch-execute": "^9.0.17", + "@graphql-tools/executor": "^1.4.7", + "@graphql-tools/schema": "^10.0.11", + "@graphql-tools/utils": "^10.8.1", + "@repeaterjs/repeater": "^3.0.6", + "@whatwg-node/promise-helpers": "^1.3.0", + "dataloader": "^2.2.3", + "dset": "^3.1.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/documents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.1.tgz", + "integrity": "sha512-aweoMH15wNJ8g7b2r4C4WRuJxZ0ca8HtNO54rkye/3duxTkW4fGBEutCx03jCIr5+a1l+4vFJNP859QnAVBVCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/executor": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.4.7.tgz", + "integrity": "sha512-U0nK9jzJRP9/9Izf1+0Gggd6K6RNRsheFo1gC/VWzfnsr0qjcOSS9qTjY0OTC5iTPt4tQ+W5Zpw/uc7mebI6aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.6", + "@graphql-typed-document-node/core": "^3.2.0", + "@repeaterjs/repeater": "^3.0.4", + "@whatwg-node/disposablestack": "^0.0.6", + "@whatwg-node/promise-helpers": "^1.0.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/executor-common": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-common/-/executor-common-0.0.4.tgz", + "integrity": "sha512-SEH/OWR+sHbknqZyROCFHcRrbZeUAyjCsgpVWCRjqjqRbiJiXq6TxNIIOmpXgkrXWW/2Ev4Wms6YSGJXjdCs6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@envelop/core": "^5.2.3", + "@graphql-tools/utils": "^10.8.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/executor-graphql-ws": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-2.0.5.tgz", + "integrity": "sha512-gI/D9VUzI1Jt1G28GYpvm5ckupgJ5O8mi5Y657UyuUozX34ErfVdZ81g6oVcKFQZ60LhCzk7jJeykK48gaLhDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/executor-common": "^0.0.4", + "@graphql-tools/utils": "^10.8.1", + "@whatwg-node/disposablestack": "^0.0.6", + "graphql-ws": "^6.0.3", + "isomorphic-ws": "^5.0.0", + "tslib": "^2.8.1", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/executor-http": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-1.3.3.tgz", + "integrity": "sha512-LIy+l08/Ivl8f8sMiHW2ebyck59JzyzO/yF9SFS4NH6MJZUezA1xThUXCDIKhHiD56h/gPojbkpcFvM2CbNE7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-hive/signal": "^1.0.0", + "@graphql-tools/executor-common": "^0.0.4", + "@graphql-tools/utils": "^10.8.1", + "@repeaterjs/repeater": "^3.0.4", + "@whatwg-node/disposablestack": "^0.0.6", + "@whatwg-node/fetch": "^0.10.4", + "@whatwg-node/promise-helpers": "^1.3.0", + "meros": "^1.2.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/executor-legacy-ws": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.1.17.tgz", + "integrity": "sha512-TvltY6eL4DY1Vt66Z8kt9jVmNcI+WkvVPQZrPbMCM3rv2Jw/sWvSwzUBezRuWX0sIckMifYVh23VPcGBUKX/wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.6", + "@types/ws": "^8.0.0", + "isomorphic-ws": "^5.0.0", + "tslib": "^2.4.0", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/git-loader": { + "version": "8.0.24", + "resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.24.tgz", + "integrity": "sha512-ypLC9N2bKNC0QNbrEBTbWKwbV607f7vK2rSGi9uFeGr8E29tWplo6or9V/+TM0ZfIkUsNp/4QX/zKTgo8SbwQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/graphql-tag-pluck": "8.3.19", + "@graphql-tools/utils": "^10.8.6", + "is-glob": "4.0.3", + "micromatch": "^4.0.8", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/github-loader": { + "version": "8.0.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-8.0.20.tgz", + "integrity": "sha512-Icch8bKZ1iP3zXCB9I0ded1hda9NPskSSalw7ZM21kXvLiOR5nZhdqPF65gCFkIKo+O4NR4Bp51MkKj+wl+vpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/executor-http": "^1.1.9", + "@graphql-tools/graphql-tag-pluck": "^8.3.19", + "@graphql-tools/utils": "^10.8.6", + "@whatwg-node/fetch": "^0.10.0", + "@whatwg-node/promise-helpers": "^1.0.0", + "sync-fetch": "0.6.0-2", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/graphql-file-loader": { + "version": "8.0.20", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.0.20.tgz", + "integrity": "sha512-inds4My+JJxmg5mxKWYtMIJNRxa7MtX+XIYqqD/nu6G4LzQ5KGaBJg6wEl103KxXli7qNOWeVAUmEjZeYhwNEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/import": "7.0.19", + "@graphql-tools/utils": "^10.8.6", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/graphql-tag-pluck": { + "version": "8.3.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.3.19.tgz", + "integrity": "sha512-LEw/6IYOUz48HjbWntZXDCzSXsOIM1AyWZrlLoJOrA8QAlhFd8h5Tny7opCypj8FO9VvpPFugWoNDh5InPOEQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "@graphql-tools/utils": "^10.8.6", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/import": { + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-7.0.19.tgz", + "integrity": "sha512-Xtku8G4bxnrr6I3hVf8RrBFGYIbQ1OYVjl7jgcy092aBkNZvy1T6EDmXmYXn5F+oLd9Bks3K3WaMm8gma/nM/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.6", + "resolve-from": "5.0.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/json-file-loader": { + "version": "8.0.18", + "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-8.0.18.tgz", + "integrity": "sha512-JjjIxxewgk8HeMR3npR3YbOkB7fxmdgmqB9kZLWdkRKBxrRXVzhryyq+mhmI0Evzt6pNoHIc3vqwmSctG2sddg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.6", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/load": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-8.1.0.tgz", + "integrity": "sha512-OGfOm09VyXdNGJS/rLqZ6ztCiG2g6AMxhwtET8GZXTbnjptFc17GtKwJ3Jv5w7mjJ8dn0BHydvIuEKEUK4ciYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/schema": "^10.0.23", + "@graphql-tools/utils": "^10.8.6", + "p-limit": "3.1.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/merge": { + "version": "9.0.24", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.24.tgz", + "integrity": "sha512-NzWx/Afl/1qHT3Nm1bghGG2l4jub28AdvtG11PoUlmjcIjnFBJMv4vqL0qnxWe8A82peWo4/TkVdjJRLXwgGEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/utils": "^10.8.6", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/optimize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/optimize/-/optimize-2.0.0.tgz", + "integrity": "sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/prisma-loader": { + "version": "8.0.17", + "resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-8.0.17.tgz", + "integrity": "sha512-fnuTLeQhqRbA156pAyzJYN0KxCjKYRU5bz1q/SKOwElSnAU4k7/G1kyVsWLh7fneY78LoMNH5n+KlFV8iQlnyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/url-loader": "^8.0.15", + "@graphql-tools/utils": "^10.5.6", + "@types/js-yaml": "^4.0.0", + "@whatwg-node/fetch": "^0.10.0", + "chalk": "^4.1.0", + "debug": "^4.3.1", + "dotenv": "^16.0.0", + "graphql-request": "^6.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "jose": "^5.0.0", + "js-yaml": "^4.0.0", + "lodash": "^4.17.20", + "scuid": "^1.1.0", + "tslib": "^2.4.0", + "yaml-ast-parser": "^0.0.43" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/relay-operation-optimizer": { + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.19.tgz", + "integrity": "sha512-xnjLpfzw63yIX1bo+BVh4j1attSwqEkUbpJ+HAhdiSUa3FOQFfpWgijRju+3i87CwhjBANqdTZbcsqLT1hEXig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ardatan/relay-compiler": "^12.0.3", + "@graphql-tools/utils": "^10.8.6", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/schema": { + "version": "10.0.23", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.23.tgz", + "integrity": "sha512-aEGVpd1PCuGEwqTXCStpEkmheTHNdMayiIKH1xDWqYp9i8yKv9FRDgkGrY4RD8TNxnf7iII+6KOBGaJ3ygH95A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/merge": "^9.0.24", + "@graphql-tools/utils": "^10.8.6", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/url-loader": { + "version": "8.0.31", + "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-8.0.31.tgz", + "integrity": "sha512-QGP3py6DAdKERHO5D38Oi+6j+v0O3rkBbnLpyOo87rmIRbwE6sOkL5JeHegHs7EEJ279fBX6lMt8ry0wBMGtyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/executor-graphql-ws": "^2.0.1", + "@graphql-tools/executor-http": "^1.1.9", + "@graphql-tools/executor-legacy-ws": "^1.1.17", + "@graphql-tools/utils": "^10.8.6", + "@graphql-tools/wrap": "^10.0.16", + "@types/ws": "^8.0.0", + "@whatwg-node/fetch": "^0.10.0", + "@whatwg-node/promise-helpers": "^1.0.0", + "isomorphic-ws": "^5.0.0", + "sync-fetch": "0.6.0-2", + "tslib": "^2.4.0", + "ws": "^8.17.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/utils": { + "version": "10.8.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.8.6.tgz", + "integrity": "sha512-Alc9Vyg0oOsGhRapfL3xvqh1zV8nKoFUdtLhXX7Ki4nClaIJXckrA86j+uxEuG3ic6j4jlM1nvcWXRn/71AVLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@whatwg-node/promise-helpers": "^1.0.0", + "cross-inspect": "1.0.1", + "dset": "^3.1.4", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/wrap": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.1.1.tgz", + "integrity": "sha512-vNtnot0QMGSpCZeSvmd2pmpnMjpPHhUMD2d7sVy6vIzRx6lPV/zc9TKMeWGLlHgVx3oKg3RefB9dv19/QAPbog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/delegate": "^10.2.20", + "@graphql-tools/schema": "^10.0.11", + "@graphql-tools/utils": "^10.8.1", + "@whatwg-node/promise-helpers": "^1.3.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", @@ -945,6 +2092,51 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@repeaterjs/repeater": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", + "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.40.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", @@ -1225,6 +2417,15 @@ "win32" ] }, + "node_modules/@solidjs/router": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@solidjs/router/-/router-0.15.3.tgz", + "integrity": "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw==", + "license": "MIT", + "peerDependencies": { + "solid-js": "^1.8.6" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1277,14 +2478,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "22.15.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.14.tgz", - "integrity": "sha512-BL1eyu/XWsFGTtDWOYULQEs4KR0qdtYfCxYAUYRoB7JP7h9ETYLgQTww6kH8Sj2C0pFGgrpM0XKv6/kbIzYJ1g==", + "version": "24.0.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.7.tgz", + "integrity": "sha512-YIEUUr4yf8q8oQoXPpSlnvKNVKDQlPMWrmOcgzoduo7kvA2UF0/BwJ/eMKFTiTtkNL17I0M6Xe2tvwFU7be6iw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/prismjs": { @@ -1294,6 +2502,73 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@whatwg-node/disposablestack": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz", + "integrity": "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/promise-helpers": "^1.0.0", + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/fetch": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.10.8.tgz", + "integrity": "sha512-Rw9z3ctmeEj8QIB9MavkNJqekiu9usBCSMZa+uuAvM0lF3v70oQVCXNppMIqaV6OTZbdaHF1M2HLow58DEw+wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@whatwg-node/node-fetch": "^0.7.21", + "urlpattern-polyfill": "^10.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/node-fetch": { + "version": "0.7.21", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.7.21.tgz", + "integrity": "sha512-QC16IdsEyIW7kZd77aodrMO7zAoDyyqRCTLg+qG4wqtP4JV9AA+p7/lgqMdD29XyiYdVvIdFrfI9yh7B1QvRvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^3.1.1", + "@whatwg-node/disposablestack": "^0.0.6", + "@whatwg-node/promise-helpers": "^1.3.2", + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@whatwg-node/promise-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz", + "integrity": "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.3" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", @@ -1307,6 +2582,109 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/auto-bind": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", + "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/babel-plugin-jsx-dom-expressions": { "version": "0.39.8", "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.39.8.tgz", @@ -1351,6 +2729,69 @@ "@babel/core": "^7.0.0" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.24.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", @@ -1384,6 +2825,41 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -1391,6 +2867,16 @@ "dev": true, "license": "MIT" }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001717", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", @@ -1412,6 +2898,453 @@ ], "license": "CC-BY-4.0" }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/capital-case/node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/capital-case/node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/capital-case/node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case-all": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz", + "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "change-case": "^4.1.2", + "is-lower-case": "^2.0.2", + "is-upper-case": "^2.0.2", + "lower-case": "^2.0.2", + "lower-case-first": "^2.0.2", + "sponge-case": "^1.0.1", + "swap-case": "^2.0.2", + "title-case": "^3.0.3", + "upper-case": "^2.0.2", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/change-case-all/node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "node_modules/change-case-all/node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/is-lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", + "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/is-upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz", + "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/lower-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz", + "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/change-case-all/node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/swap-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz", + "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/title-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", + "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/change-case-all/node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -1419,6 +3352,16 @@ "dev": true, "license": "MIT" }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1426,10 +3369,133 @@ "dev": true, "license": "MIT" }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cosmiconfig/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-inspect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.1.tgz", + "integrity": "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/dataloader": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz", + "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", "dev": true, "license": "MIT" }, @@ -1451,6 +3517,95 @@ } } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.150", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.150.tgz", @@ -1458,6 +3613,25 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/entities": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", @@ -1471,6 +3645,16 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/esbuild": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", @@ -1522,10 +3706,108 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "dev": true, + "license": "MIT" + }, "node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1537,6 +3819,72 @@ } } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1562,6 +3910,19 @@ "node": ">=6.9.0" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -1572,6 +3933,27 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graphql": { "version": "16.11.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", @@ -1582,6 +3964,119 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, + "node_modules/graphql-config": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.1.5.tgz", + "integrity": "sha512-mG2LL1HccpU8qg5ajLROgdsBzx/o2M6kgI3uAmoaXiSH9PCUbtIyLomLqUtCFaAeG2YCFsl0M5cfQ9rKmDoMVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-tools/graphql-file-loader": "^8.0.0", + "@graphql-tools/json-file-loader": "^8.0.0", + "@graphql-tools/load": "^8.1.0", + "@graphql-tools/merge": "^9.0.0", + "@graphql-tools/url-loader": "^8.0.0", + "@graphql-tools/utils": "^10.0.0", + "cosmiconfig": "^8.1.0", + "jiti": "^2.0.0", + "minimatch": "^9.0.5", + "string-env-interpolation": "^1.0.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "cosmiconfig-toml-loader": "^1.0.0", + "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + }, + "peerDependenciesMeta": { + "cosmiconfig-toml-loader": { + "optional": true + } + } + }, + "node_modules/graphql-config/node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-ws": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-6.0.5.tgz", + "integrity": "sha512-HzYw057ch0hx2gZjkbgk1pur4kAtgljlWRP+Gccudqm3BRrTpExjWCQ9OHdIsq47Y6lHL++1lTvuQHhgRRcevw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@fastify/websocket": "^10 || ^11", + "crossws": "~0.3", + "graphql": "^15.10.1 || ^16", + "uWebSockets.js": "^20", + "ws": "^8" + }, + "peerDependenciesMeta": { + "@fastify/websocket": { + "optional": true + }, + "crossws": { + "optional": true + }, + "uWebSockets.js": { + "optional": true + }, + "ws": { + "optional": true + } + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/html-entities": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", @@ -1589,6 +4084,350 @@ "dev": true, "license": "MIT" }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", + "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", + "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-what": { "version": "4.1.16", "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", @@ -1602,6 +4441,46 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jose": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", + "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1609,6 +4488,19 @@ "dev": true, "license": "MIT" }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -1622,6 +4514,27 @@ "node": ">=6" } }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-to-pretty-yaml": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", + "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "remedial": "^1.0.7", + "remove-trailing-spaces": "^1.0.6" + }, + "engines": { + "node": ">= 0.2.0" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -1635,6 +4548,490 @@ "node": ">=6" } }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -1645,6 +5042,16 @@ "yallist": "^3.0.2" } }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/merge-anything": { "version": "5.1.7", "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.1.7.tgz", @@ -1661,6 +5068,87 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/meros": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.1.tgz", + "integrity": "sha512-eV7dRObfTrckdmAz4/n7pT1njIsIJXRIZkgCiX43xEsPNy4gjXQzOYYxmGcolAMtF7HyfqRuDBh3Lgs4hmhVEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=13" + }, + "peerDependencies": { + "@types/node": ">=13" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1668,6 +5156,13 @@ "dev": true, "license": "MIT" }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -1687,6 +5182,34 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -1694,6 +5217,169 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/parse5": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", @@ -1707,6 +5393,29 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1728,9 +5437,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -1748,7 +5457,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -1760,11 +5469,146 @@ "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/relay-runtime": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-12.0.0.tgz", + "integrity": "sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.0.0", + "fbjs": "^3.0.0", + "invariant": "^2.2.4" + } + }, + "node_modules/remedial": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", + "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "engines": { + "node": "*" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "license": "ISC" + }, + "node_modules/remove-trailing-spaces": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.9.tgz", + "integrity": "sha512-xzG7w5IRijvIkHIjDk65URsJJ7k4J95wmcArY5PRcmjldIOl7oTvG8+X2Ag690R7SfwiOcHrWZKVc1Pp5WIOzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rollup": { "version": "4.40.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", @@ -1805,6 +5649,85 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/scuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz", + "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1819,7 +5742,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.0.tgz", "integrity": "sha512-4tYQDy3HVM0JjJ1CfDK3K8FhBKIDDri27oc2AyabuuHfQw6/yTDPp2Abt1h2cNtf1R0T+7AQYAzPhUgqXztaXw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -1829,7 +5751,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.3.0.tgz", "integrity": "sha512-FFu/UE3uA8L1vj0CXXZo2Nlh10MtYoOs0G//ptwlQMjfPFSeIVYUNy0zewfV8iM0CrOebAfHEG6J3xA9c+lsaQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -1838,16 +5759,84 @@ "seroval": "^1.0" } }, - "node_modules/solid-js": { - "version": "1.9.6", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.6.tgz", - "integrity": "sha512-PoasAJvLk60hRtOTe9ulvALOdLjjqxuxcGZRolBQqxOnXrBXHGzqMT4ijNhGsDAYdOgEa8ZYaAE94PSldrFSkA==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/signedsource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/signedsource/-/signedsource-1.0.0.tgz", + "integrity": "sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/solid-js": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.7.tgz", + "integrity": "sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==", + "license": "MIT", "dependencies": { "csstype": "^3.1.0", - "seroval": "^1.1.0", - "seroval-plugins": "^1.1.0" + "seroval": "~1.3.0", + "seroval-plugins": "~1.3.0" } }, "node_modules/solid-refresh": { @@ -1896,6 +5885,80 @@ "source-map": "^0.6.0" } }, + "node_modules/sponge-case": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz", + "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-env-interpolation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", + "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sync-fetch": { + "version": "0.6.0-2", + "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0-2.tgz", + "integrity": "sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^3.3.2", + "timeout-signal": "^2.0.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/sync-fetch/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/terser": { "version": "5.39.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", @@ -1915,10 +5978,27 @@ "node": ">=10" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/timeout-signal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/timeout-signal/-/timeout-signal-2.0.0.tgz", + "integrity": "sha512-YBGpG4bWsHoPvofT6y/5iqulfXIiIErl5B0LdtHT1mGXDFTAhhRrbUpTvBgYbovr+3cKblya2WAOcpoy90XguA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1932,6 +6012,66 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ts-log": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.7.tgz", + "integrity": "sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -1946,13 +6086,63 @@ "node": ">=14.17" } }, + "node_modules/ua-parser-js": { + "version": "1.0.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", + "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true, "license": "MIT" }, + "node_modules/unixify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", + "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "normalize-path": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -1984,6 +6174,20 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/validate-html-nesting": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/validate-html-nesting/-/validate-html-nesting-1.2.2.tgz", @@ -1992,24 +6196,24 @@ "license": "ISC" }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.0.tgz", + "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.4", + "fdir": "^6.4.6", "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "postcss": "^8.5.6", + "rollup": "^4.40.0", + "tinyglobby": "^0.2.14" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -2018,14 +6222,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -2067,9 +6271,9 @@ } }, "node_modules/vite-plugin-solid": { - "version": "2.11.6", - "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.11.6.tgz", - "integrity": "sha512-Sl5CTqJTGyEeOsmdH6BOgalIZlwH3t4/y0RQuFLMGnvWMBvxb4+lq7x3BSiAw6etf0QexfNJW7HSOO/Qf7pigg==", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.11.7.tgz", + "integrity": "sha512-5TgK1RnE449g0Ryxb9BXqem89RSy7fE8XGVCo+Gw84IHgPuPVP7nYNP6WBVAaY/0xw+OqfdQee+kusL0y3XYNg==", "dev": true, "license": "MIT", "dependencies": { @@ -2110,12 +6314,115 @@ } } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yaml-ast-parser": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", + "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 1ecd1d7b..31e5370e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "admin-panel", - "version": "0.4.22", + "name": "publy-panel", + "version": "0.5.8", "private": true, "scripts": { "dev": "vite", @@ -8,20 +8,33 @@ "serve": "vite preview", "lint": "biome check . --fix", "format": "biome format . --write", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "codegen": "graphql-codegen --config codegen.ts", + "codegen:watch": "graphql-codegen --config codegen.ts --watch" }, "devDependencies": { - "@biomejs/biome": "^1.9.4", - "@types/node": "^22.15.0", + "@biomejs/biome": "^2.0.6", + "@graphql-codegen/cli": "^5.0.7", + "@graphql-codegen/client-preset": "^4.8.3", + "@graphql-codegen/typescript": "^4.0.6", + "@graphql-codegen/typescript-operations": "^4.2.0", + "@graphql-codegen/typescript-resolvers": "^4.0.6", + "@types/node": "^24.0.7", "@types/prismjs": "^1.26.5", - "graphql": "^16.8.0", - "solid-js": "^1.9.6", + "graphql": "^16.11.0", + "graphql-tag": "^2.12.6", + "lightningcss": "^1.30.0", + "prismjs": "^1.30.0", + "solid-js": "^1.9.7", "terser": "^5.39.0", - "typescript": "^5.8.0", - "vite": "^6.3.0", - "vite-plugin-solid": "^2.11.0" + "typescript": "^5.8.3", + "vite": "^7.0.0", + "vite-plugin-solid": "^2.11.7" + }, + "overrides": { + "vite": "^7.0.0" }, "dependencies": { - "prismjs": "^1.30.0" + "@solidjs/router": "^0.15.3" } } diff --git a/panel/App.tsx b/panel/App.tsx index 479935d2..d2cf4ffc 100644 --- a/panel/App.tsx +++ b/panel/App.tsx @@ -1,105 +1,89 @@ -import { Component, Show, Suspense, createSignal, lazy, onMount, createEffect } from 'solid-js' -import { isAuthenticated, getAuthTokenFromCookie } from './auth' +import { Route, Router } from '@solidjs/router' +import { lazy, onMount, Suspense } from 'solid-js' +import { AuthProvider, useAuth } from './context/auth' // Ленивая загрузка компонентов -const AdminPage = lazy(() => import('./admin')) -const LoginPage = lazy(() => import('./login')) +const AdminPage = lazy(() => { + console.log('[App] Loading AdminPage component...') + return import('./admin') +}) +const LoginPage = lazy(() => { + console.log('[App] Loading LoginPage component...') + return import('./routes/login') +}) /** - * Корневой компонент приложения с простой логикой отображения + * Компонент защищенного маршрута */ -const App: Component = () => { - const [authenticated, setAuthenticated] = createSignal(null) - const [loading, setLoading] = createSignal(true) - const [checkingAuth, setCheckingAuth] = createSignal(true) +const ProtectedRoute = () => { + console.log('[ProtectedRoute] Checking authentication...') + const auth = useAuth() + const authenticated = auth.isAuthenticated() + console.log( + `[ProtectedRoute] Authentication state: ${authenticated ? 'authenticated' : 'not authenticated'}` + ) - // Проверяем авторизацию при монтировании - onMount(() => { - checkAuthentication() - }) - - // Периодическая проверка авторизации - createEffect(() => { - const authCheckInterval = setInterval(() => { - // Перепроверяем статус авторизации каждые 60 секунд - if (!checkingAuth()) { - const authed = isAuthenticated() - if (!authed && authenticated()) { - console.log('Сессия истекла, требуется повторная авторизация') - setAuthenticated(false) - } - } - }, 60000) - - return () => clearInterval(authCheckInterval) - }) - - // Функция проверки авторизации - const checkAuthentication = async () => { - setCheckingAuth(true) - setLoading(true) - - try { - // Проверяем состояние авторизации - const authed = isAuthenticated() - - // Если токен есть, но он невалидный, авторизация не удалась - if (authed) { - const token = getAuthTokenFromCookie() || localStorage.getItem('auth_token') - if (!token || token.length < 10) { - setAuthenticated(false) - } else { - setAuthenticated(true) - } - } else { - setAuthenticated(false) - } - } catch (error) { - console.error('Ошибка при проверке авторизации:', error) - setAuthenticated(false) - } finally { - setLoading(false) - setCheckingAuth(false) - } - } - - // Обработчик успешной авторизации - const handleLoginSuccess = () => { - setAuthenticated(true) - } - - // Обработчик выхода из системы - const handleLogout = () => { - setAuthenticated(false) + if (!authenticated) { + console.log('[ProtectedRoute] Not authenticated, redirecting to login...') + // Используем window.location.href для редиректа + window.location.href = '/login' + return ( +
+
+
Проверка авторизации...
+
+ ) } return ( -
- -
-

Загрузка компонентов...

-
- } - > - -
-

Проверка авторизации...

-
- } - > - {authenticated() ? ( - - ) : ( - - )} -
-
-
+ +
+
Загрузка админ-панели...
+
+ } + > + +
+ ) +} + +/** + * Корневой компонент приложения + */ +const App = () => { + console.log('[App] Initializing root component...') + + onMount(() => { + console.log('[App] Root component mounted') + }) + + return ( + +
+ + ( + +
+
Загрузка страницы входа...
+
+ } + > + +
+ )} + /> + + + +
+
+
) } diff --git a/panel/admin.tsx b/panel/admin.tsx index ef144eba..0dda19bd 100644 --- a/panel/admin.tsx +++ b/panel/admin.tsx @@ -3,225 +3,23 @@ * @module AdminPage */ -import { Component, For, Show, createSignal, onMount, createEffect } from 'solid-js' -import { logout } from './auth' -import { query } from './graphql' -import Prism from 'prismjs' -import 'prismjs/components/prism-json' -import 'prismjs/components/prism-markup' -import 'prismjs/themes/prism-tomorrow.css' - -// Определяем GraphQL запрос -const ADMIN_GET_SHOUTS_QUERY = ` - query AdminGetShouts($limit: Int, $offset: Int, $status: String) { - adminGetShouts(limit: $limit, offset: $offset, status: $status) { - shouts { - id - title - slug - body - lead - subtitle - layout - lang - cover - cover_caption - media { - url - title - body - source - pic - date - genre - artist - lyrics - } - seo - created_at - updated_at - published_at - featured_at - deleted_at - created_by { - id - email - name - } - authors { - id - email - name - slug - } - topics { - id - title - slug - } - version_of - draft - } - total - page - perPage - totalPages - } - } -` - -/** - * Интерфейс для данных пользователя - */ -interface User { - id: number - email: string - name?: string - slug?: string - roles: string[] - created_at?: number - last_seen?: number -} - -/** - * Интерфейс для роли пользователя - */ -interface Role { - id: string // ID роли - строка, не число - name: string - description?: string -} - -/** - * Интерфейс для ответа API с пользователями - */ -interface AdminGetUsersResponse { - adminGetUsers: { - users: User[] - total: number - page: number - perPage: number - totalPages: number - } -} - -/** - * Интерфейс для ответа API с ролями - */ -interface AdminGetRolesResponse { - adminGetRoles: Role[] -} - -/** - * Интерфейс для ответа обновления пользователя - */ -interface AdminUpdateUserResponse { - success: boolean - error?: string -} - -/** - * Интерфейс для входных данных обновления пользователя - */ -interface AdminUserUpdateInput { - id: number - roles: string[] - community?: number -} - -/** - * Интерфейс для переменной окружения - */ -interface EnvVariable { - key: string - value: string - description?: string - type: string - isSecret: boolean -} - -/** - * Интерфейс для секции переменных окружения - */ -interface EnvSection { - name: string - description?: string - variables: EnvVariable[] -} - -/** - * Интерфейс для публикации - */ -interface Shout { - id: number - title: string - slug: string - body: string - lead?: string - subtitle?: string - layout: string - lang: string - cover?: string - cover_caption?: string - media?: any[] - seo?: string - created_at: number - updated_at?: number - published_at?: number - featured_at?: number - deleted_at?: number - created_by: { - id: number - email?: string - name?: string - } - updated_by?: { - id: number - email?: string - name?: string - } - deleted_by?: { - id: number - email?: string - name?: string - } - community: { - id: number - name?: string - } - authors?: Array<{ - id: number - email?: string - name?: string - slug?: string - }> - topics?: Array<{ - id: number - title?: string - slug?: string - }> - version_of?: number - draft?: number - stat?: any -} - -/** - * Интерфейс для ответа API с публикациями - */ -interface AdminGetShoutsData { - adminGetShouts: { - shouts: any[] - total: number - page: number - perPage: number - totalPages: number - } -} +import { useNavigate, useParams } from '@solidjs/router' +import { Component, createEffect, createSignal, onMount, Show } from 'solid-js' +import publyLogo from './assets/publy.svg?url' +import { logout } from './context/auth' +// Прямой импорт компонентов вместо ленивой загрузки +import AuthorsRoute from './routes/authors' +import CommunitiesRoute from './routes/communities' +import EnvRoute from './routes/env' +import ShoutsRoute from './routes/shouts' +import TopicsRoute from './routes/topics' +import styles from './styles/Admin.module.css' +import Button from './ui/Button' /** * Интерфейс свойств компонента AdminPage */ -interface AdminPageProps { +export interface AdminPageProps { apiUrl: string onLogout?: () => void } @@ -230,297 +28,38 @@ interface AdminPageProps { * Компонент страницы администратора */ const AdminPage: Component = (props) => { - const [activeTab, setActiveTab] = createSignal('users') - const [users, setUsers] = createSignal([]) - const [roles, setRoles] = createSignal([]) - const [loading, setLoading] = createSignal(true) + console.log('[AdminPage] Initializing...') + const navigate = useNavigate() + const params = useParams() const [error, setError] = createSignal(null) - const [selectedUser, setSelectedUser] = createSignal(null) - const [showRolesModal, setShowRolesModal] = createSignal(false) const [successMessage, setSuccessMessage] = createSignal(null) - const [showBodyModal, setShowBodyModal] = createSignal(false) - const [selectedShoutBody, setSelectedShoutBody] = createSignal('') - const [showMediaBodyModal, setShowMediaBodyModal] = createSignal(false) - const [selectedMediaBody, setSelectedMediaBody] = createSignal('') + const [currentTab, setCurrentTab] = createSignal('authors') - // Переменные среды - const [envSections, setEnvSections] = createSignal([]) - const [envLoading, setEnvLoading] = createSignal(false) - const [editingVariable, setEditingVariable] = createSignal(null) - const [showVariableModal, setShowVariableModal] = createSignal(false) - - // Параметры пагинации - const [pagination, setPagination] = createSignal<{ - page: number - limit: number - total: number - totalPages: number - }>({ - page: 1, - limit: 10, - total: 0, - totalPages: 1 + onMount(() => { + console.log('[AdminPage] Component mounted') + console.log('[AdminPage] Initial params:', params) + // Если мы на корневом пути /admin, редиректим на /admin/authors + if (!params.tab) { + navigate('/admin/authors', { replace: true }) + } else { + setCurrentTab(params.tab) + } }) - // Поиск - const [searchQuery, setSearchQuery] = createSignal('') - - // Публикации - const [shouts, setShouts] = createSignal([]) - const [shoutsLoading, setShoutsLoading] = createSignal(false) - const [shoutsStatus, setShoutsStatus] = createSignal('all') // all, published, draft, deleted - const [shoutsPagination, setShoutsPagination] = createSignal<{ - page: number - limit: number - total: number - totalPages: number - }>({ - page: 1, - limit: 20, - total: 0, - totalPages: 0 + // Отслеживаем изменения параметров роута + createEffect(() => { + console.log('[AdminPage] Params changed:', params) + console.log('[AdminPage] Current tab param:', params.tab) + const newTab = params.tab || 'authors' + setCurrentTab(newTab) + console.log('[AdminPage] Updated currentTab to:', newTab) }) - const [shoutsSearchQuery, setShoutsSearchQuery] = createSignal('') - /** - * Загрузка списка пользователей с учетом пагинации и поиска - */ - async function loadUsers() { - setLoading(true) - setError(null) - - try { - // Используем актуальные данные из состояния - const { page, limit } = pagination() - const offset = (page - 1) * limit - const search = searchQuery().trim() - - const data = await query( - `${location.origin}/graphql`, - ` - query AdminGetUsers($limit: Int, $offset: Int, $search: String) { - adminGetUsers(limit: $limit, offset: $offset, search: $search) { - users { - id - email - name - slug - roles - created_at - last_seen - } - total - page - perPage - totalPages - } - } - `, - { limit, offset, search: search || null } - ) - - if (data?.adminGetUsers) { - setUsers(data.adminGetUsers.users) - setPagination({ - page: data.adminGetUsers.page, - limit: data.adminGetUsers.perPage, - total: data.adminGetUsers.total, - totalPages: data.adminGetUsers.totalPages - }) - } - } catch (err) { - console.error('Ошибка загрузки пользователей:', err) - setError(err instanceof Error ? err.message : 'Неизвестная ошибка') - - // Если ошибка авторизации - перенаправляем на логин - if ( - err instanceof Error && - (err.message.includes('401') || - err.message.includes('авторизации') || - err.message.includes('unauthorized') || - err.message.includes('Unauthorized')) - ) { - handleLogout() - } - } finally { - setLoading(false) - } - } - - /** - * Загрузка списка ролей - */ - async function loadRoles() { - try { - const data = await query( - `${location.origin}/graphql`, - ` - query AdminGetRoles { - adminGetRoles { - id - name - description - } - } - ` - ) - - if (data?.adminGetRoles) { - setRoles(data.adminGetRoles) - } - } catch (err) { - console.error('Ошибка при загрузке ролей:', err) - setError('Не удалось загрузить роли') - } - } - - /** - * Загрузка списка публикаций с учетом пагинации и поиска - */ - async function loadShouts() { - setShowRolesModal(false) - setShoutsLoading(true) - const pagination = shoutsPagination() - - try { - const result = await query( - `${location.origin}/graphql`, - ADMIN_GET_SHOUTS_QUERY, - { - offset: (pagination.page - 1) * pagination.limit, - limit: pagination.limit, - status: shoutsStatus() - } - ) - - if (result?.adminGetShouts) { - setShouts(result.adminGetShouts.shouts) - // Обновляем пагинацию с учетом общего количества - setShoutsPagination({ - ...pagination, - total: result.adminGetShouts.total, - totalPages: result.adminGetShouts.totalPages - }) - } - } catch (error) { - console.error('Error loading shouts:', error) - } finally { - setShoutsLoading(false) - } - } - - /** - * Обработчик изменения страницы - * @param page - Номер страницы - */ - function handlePageChange(page: number) { - setPagination({ ...pagination(), page }) - loadUsers() - } - - /** - * Обработчик изменения количества элементов на странице - * @param limit - Количество элементов - */ - function handlePerPageChange(limit: number) { - setPagination({ ...pagination(), page: 1, limit }) - loadUsers() - } - - /** - * Обработчик изменения поискового запроса - */ - function handleSearchChange(e: Event) { - const input = e.target as HTMLInputElement - setSearchQuery(input.value) - } - - /** - * Выполняет поиск - */ - function handleSearch() { - setPagination({ ...pagination(), page: 1 }) - loadUsers() - } - - /** - * Обработчик нажатия клавиш в поле поиска - * @param e - Событие клавиатуры - */ - function handleSearchKeyDown(e: KeyboardEvent) { - // Если нажат Enter, выполняем поиск - if (e.key === 'Enter') { - e.preventDefault() - handleSearch() - } - } - - /** - * Закрывает модальное окно ролей - */ - function closeRolesModal() { - setShowRolesModal(false) - setSelectedUser(null) - } - - /** - * Обновляет роли пользователя - * @param userId - ID пользователя - * @param roles - Новый список ролей - */ - async function updateUserRoles(userId: number, newRoles: string[]) { - try { - await query( - `${location.origin}/graphql`, - ` - mutation AdminUpdateUser($user: AdminUserUpdateInput!) { - adminUpdateUser(user: $user) { - success - error - } - } - `, - { - user: { - id: userId, - roles: newRoles, - community: 1 // Добавляем обязательный параметр community - } - } - ) - - // Обновляем роли пользователя в списке - setUsers((prev) => - prev.map((user) => { - if (user.id === userId) { - return { ...user, roles: newRoles } - } - return user - }) - ) - - // Закрываем модальное окно - closeRolesModal() - - // Показываем сообщение об успехе и обновляем список пользователей - setSuccessMessage('Роли пользователя успешно обновлены') - - // Перезагружаем список пользователей - loadUsers() - - // Скрываем сообщение через 3 секунды - setTimeout(() => setSuccessMessage(null), 3000) - } catch (err) { - console.error('Ошибка обновления ролей:', err) - let errorMessage = err instanceof Error ? err.message : 'Ошибка обновления ролей'; - - // Если ошибка связана с недостающим полем community - if (errorMessage.includes('author_role.community')) { - errorMessage = 'Ошибка: для роли author требуется указать community. Обратитесь к администратору.'; - } - - setError(errorMessage) - } + // Определяем активную вкладку + const activeTab = () => { + const tab = currentTab() + console.log('[AdminPage] activeTab() returning:', tab) + return tab } /** @@ -532,1182 +71,107 @@ const AdminPage: Component = (props) => { if (props.onLogout) { props.onLogout() } + navigate('/login') } catch (error) { - setError('Ошибка при выходе: ' + (error as Error).message) + setError(`Ошибка при выходе: ${(error as Error).message}`) } } /** - * Форматирование даты в формате "X дней назад" - * @param timestamp - Временная метка - * @returns Форматированная строка с относительной датой + * Обработчик ошибок */ - function formatDateRelative(timestamp?: number): string { - if (!timestamp) return 'Н/Д' - - const now = Math.floor(Date.now() / 1000) - const diff = now - timestamp - - // Меньше минуты - if (diff < 60) { - return 'только что' - } - - // Меньше часа - if (diff < 3600) { - const minutes = Math.floor(diff / 60) - return `${minutes} ${getMinutesForm(minutes)} назад` - } - - // Меньше суток - if (diff < 86400) { - const hours = Math.floor(diff / 3600) - return `${hours} ${getHoursForm(hours)} назад` - } - - // Меньше 30 дней - if (diff < 2592000) { - const days = Math.floor(diff / 86400) - return `${days} ${getDaysForm(days)} назад` - } - - // Меньше года - if (diff < 31536000) { - const months = Math.floor(diff / 2592000) - return `${months} ${getMonthsForm(months)} назад` - } - - // Больше года - const years = Math.floor(diff / 31536000) - return `${years} ${getYearsForm(years)} назад` + const handleError = (error: string) => { + setError(error) + // Скрываем ошибку через 5 секунд + setTimeout(() => setError(null), 5000) } /** - * Получение правильной формы слова "минута" в зависимости от числа - * @param minutes - Количество минут + * Обработчик успешных операций */ - function getMinutesForm(minutes: number): string { - if (minutes % 10 === 1 && minutes % 100 !== 11) { - return 'минуту' - } else if ([2, 3, 4].includes(minutes % 10) && ![12, 13, 14].includes(minutes % 100)) { - return 'минуты' - } - return 'минут' - } - - /** - * Получение правильной формы слова "час" в зависимости от числа - * @param hours - Количество часов - */ - function getHoursForm(hours: number): string { - if (hours % 10 === 1 && hours % 100 !== 11) { - return 'час' - } else if ([2, 3, 4].includes(hours % 10) && ![12, 13, 14].includes(hours % 100)) { - return 'часа' - } - return 'часов' - } - - /** - * Получение правильной формы слова "день" в зависимости от числа - * @param days - Количество дней - */ - function getDaysForm(days: number): string { - if (days % 10 === 1 && days % 100 !== 11) { - return 'день' - } else if ([2, 3, 4].includes(days % 10) && ![12, 13, 14].includes(days % 100)) { - return 'дня' - } - return 'дней' - } - - /** - * Получение правильной формы слова "месяц" в зависимости от числа - * @param months - Количество месяцев - */ - function getMonthsForm(months: number): string { - if (months % 10 === 1 && months % 100 !== 11) { - return 'месяц' - } else if ([2, 3, 4].includes(months % 10) && ![12, 13, 14].includes(months % 100)) { - return 'месяца' - } - return 'месяцев' - } - - /** - * Получение правильной формы слова "год" в зависимости от числа - * @param years - Количество лет - */ - function getYearsForm(years: number): string { - if (years % 10 === 1 && years % 100 !== 11) { - return 'год' - } else if ([2, 3, 4].includes(years % 10) && ![12, 13, 14].includes(years % 100)) { - return 'года' - } - return 'лет' - } - - /** - * Получает иконку для роли пользователя - * @param role - Название роли - * @returns Иконка для роли - */ - function getRoleIcon(role: string): string { - switch (role.toLowerCase()) { - case 'admin': - return '👑' // корона для администратора - case 'moderator': - return '🛡️' // щит для модератора - case 'editor': - return '✏️' // карандаш для редактора - case 'author': - return '📝' // блокнот для автора - case 'user': - return '👤' // фигура для обычного пользователя - case 'subscriber': - return '📬' // почтовый ящик для подписчика - case 'guest': - return '👋' // рука для гостя - case 'banned': - return '🚫' // знак запрета для заблокированного - case 'vip': - return '⭐' // звезда для VIP - case 'verified': - return '✓' // галочка для верифицированного - default: - return '🔹' // точка для прочих ролей - } - } - - /** - * Компонент для отображения роли с иконкой - */ - const RoleBadge: Component<{ role: string }> = (props) => { - return ( - - {getRoleIcon(props.role)} - {props.role} - - ) - } - - /** - * Форматирование даты - * @param timestamp - Временная метка - */ - function formatDate(timestamp?: number): string { - if (!timestamp) return 'Н/Д' - return new Date(timestamp * 1000).toLocaleString('ru') - } - - /** - * Формирует массив номеров страниц для отображения в пагинации - * @returns Массив номеров страниц - */ - function getPageNumbers(): number[] { - const result: number[] = [] - const maxVisible = 5 // Максимальное количество видимых номеров страниц - - const paginationData = pagination() - const currentPage = paginationData.page - const totalPages = paginationData.totalPages - - let startPage = Math.max(1, currentPage - Math.floor(maxVisible / 2)) - const endPage = Math.min(totalPages, startPage + maxVisible - 1) - - // Если endPage достиг предела, сдвигаем startPage назад - if (endPage - startPage + 1 < maxVisible && startPage > 1) { - startPage = Math.max(1, endPage - maxVisible + 1) - } - - // Генерируем номера страниц - for (let i = startPage; i <= endPage; i++) { - result.push(i) - } - - return result - } - - /** - * Компонент пагинации - */ - const Pagination: Component = () => { - const paginationData = pagination() - const currentPage = paginationData.page - const total = paginationData.totalPages - - return ( - - ) - } - - /** - * Компонент модального окна для управления ролями - */ - const RolesModal: Component = () => { - const user = selectedUser() - const [selectedRoles, setSelectedRoles] = createSignal(user ? [...user.roles] : []) - const availableRoles = roles(); // Получаем список доступных ролей - - // Получаем дополнительные описания ролей - const getRoleDescription = (roleId: string): string => { - // Иначе возвращаем стандартное описание - switch(roleId) { - case 'reader': - return 'Базовая роль. Позволяет авторизоваться и оставлять реакции.'; - case 'expert': - return 'Эксперт. Позволяет оставлять комментарии и апрувить публикации для главной.'; - case 'author': - return 'Расширенная роль. Позволяет создавать контент и голосовать за публикации для вывода на главную страницу.'; - case 'editor': - return 'Редактор. Позволяет редактировать темы и публикации сообщества.'; - case 'moderator': - return 'Модератор. Позволяет модерировать контент и управлять пользователями.'; - case 'admin': - return 'Администратор. Позволяет управлять всеми функциями системы.'; - default: - return 'Нет описания'; - } - }; - - const toggleRole = (role: string) => { - const current = selectedRoles() - if (current.includes(role)) { - setSelectedRoles(current.filter((r) => r !== role)) - } else { - setSelectedRoles([...current, role]) - } - } - - const saveRoles = () => { - if (user) { - // При сохранении ролей передаем правильный набор параметров - updateUserRoles(user.id, selectedRoles()) - } - } - - if (!user) return null - - return ( - - ) - } - - /** - * Загружает переменные окружения - */ - const loadEnvVariables = async () => { - try { - setEnvLoading(true) - setError(null) - - const result = await query(props.apiUrl, ` - query GetEnvVariables { - getEnvVariables { - name - description - variables { - key - value - description - type - isSecret - } - } - } - `) - - if (result.getEnvVariables) { - setEnvSections(result.getEnvVariables as EnvSection[]) - } - } catch (err) { - console.error('Ошибка загрузки переменных окружения:', err) - setError('Не удалось загрузить переменные окружения: ' + (err as Error).message) - - // Если ошибка авторизации - перенаправляем на логин - if ( - err instanceof Error && - (err.message.includes('401') || - err.message.includes('авторизации') || - err.message.includes('unauthorized') || - err.message.includes('Unauthorized')) - ) { - handleLogout() - } - } finally { - setEnvLoading(false) - } - } - - /** - * Обновляет значение переменной окружения - */ - const updateEnvVariable = async (key: string, value: string) => { - try { - setError(null) - setSuccessMessage(null) - - const result = await query(props.apiUrl, ` - mutation UpdateEnvVariable($key: String!, $value: String!) { - updateEnvVariable(key: $key, value: $value) - } - `, { key, value }) - - if (result.updateEnvVariable) { - setSuccessMessage(`Переменная ${key} успешно обновлена`) - // Обновляем список переменных - await loadEnvVariables() - } else { - setError('Не удалось обновить переменную') - } - } catch (err) { - console.error('Ошибка обновления переменной:', err) - setError('Ошибка при обновлении переменной: ' + (err as Error).message) - - // Если ошибка авторизации - перенаправляем на логин - if ( - err instanceof Error && - (err.message.includes('401') || - err.message.includes('авторизации') || - err.message.includes('unauthorized') || - err.message.includes('Unauthorized')) - ) { - handleLogout() - } - } - } - - /** - * Обработчик открытия модального окна редактирования переменной - */ - const openVariableModal = (variable: EnvVariable) => { - setEditingVariable({ ...variable }) - setShowVariableModal(true) - } - - /** - * Обработчик закрытия модального окна редактирования переменной - */ - const closeVariableModal = () => { - setEditingVariable(null) - setShowVariableModal(false) - } - - /** - * Обработчик сохранения переменной - */ - const saveVariable = async () => { - const variable = editingVariable() - if (!variable) return - - await updateEnvVariable(variable.key, variable.value) - closeVariableModal() - } - - /** - * Обработчик изменения значения в модальном окне - */ - const handleVariableValueChange = (value: string) => { - const variable = editingVariable() - if (variable) { - setEditingVariable({ ...variable, value }) - } - } - - /** - * Загружает список переменных среды при переключении на соответствующую вкладку - */ - const handleTabChange = (tab: string) => { - setActiveTab(tab) - setError(null) - setSuccessMessage(null) - - if (tab === 'env' && envSections().length === 0) { - loadEnvVariables() - } else if (tab === 'shouts' && shouts().length === 0) { - loadShouts() - } - } - - /** - * Кнопка копирования значения переменной окружения - * @param value - значение для копирования - */ - function CopyButton({ value }: { value: string }) { - /** - * Копирует значение в буфер обмена - * @param e - событие клика - */ - const handleCopy = async (e: MouseEvent) => { - e.preventDefault() - try { - await navigator.clipboard.writeText(value) - // Можно добавить всплывающее уведомление - } catch (err) { - alert('Ошибка копирования: ' + (err as Error).message) - } - } - return ( - - 📋 - - ) - } - - /** - * Кнопка показать/скрыть значение переменной - * @param shown - показывать ли значение - * @param onToggle - обработчик переключения - */ - function ShowHideButton({ shown, onToggle }: { shown: boolean, onToggle: () => void }) { - return ( - - {shown ? '🙈' : '👁️'} - - ) - } - - /** - * Компонент модального окна для редактирования переменной окружения - */ - const VariableModal: Component = () => { - const variable = editingVariable() - - if (!variable) return null - - return ( - - ) - } - - /** - * Компонент для отображения переменных окружения - */ - const EnvVariablesTab: Component = () => { - // Сигналы для показа/скрытия значений по ключу - const [shownVars, setShownVars] = createSignal<{ [key: string]: boolean }>({}) - - /** - * Переключает показ значения переменной - * @param key - ключ переменной - */ - const toggleShow = (key: string) => { - setShownVars((prev) => ({ ...prev, [key]: !prev[key] })) - } - - return ( -
- -
Загрузка переменных окружения...
-
- - -
Нет доступных переменных окружения
-
- - 0}> -
- - {(section) => ( -
-

{section.name}

- -

{section.description}

-
-
- - - - - - - - - - - - {(variable) => { - const shown = () => shownVars()[variable.key] || false - return ( - - - - - - - ) - }} - - -
КлючЗначениеОписаниеДействия
{variable.key} - {variable.isSecret && !shown() - ? '••••••••' - : (variable.value || не задано)} - - {variable.isSecret && ( - toggleShow(variable.key)} /> - )} - {variable.description || '-'} - -
-
-
- )} -
-
-
-
- ) - } - - // Вспомогательные функции для публикаций - function getShoutStatus(shout: Shout): string { - if (shout.deleted_at) return 'Удалена' - if (shout.published_at) return 'Опубликована' - return 'Черновик' - } - - function getShoutStatusClass(shout: Shout): string { - if (shout.deleted_at) return 'status-deleted' - if (shout.published_at) return 'status-published' - return 'status-draft' - } - - function truncateText(text: string, maxLength: number = 100): string { - if (!text || text.length <= maxLength) return text - return text.substring(0, maxLength) + '...' - } - - /** - * Определяет язык контента (html или json) - */ - function detectLanguage(content: string): string { - // Пробуем распарсить как JSON - try { - JSON.parse(content) - return 'json' - } catch { - // Проверяем на наличие HTML тегов - if (/<[^>]*>/g.test(content)) { - return 'markup' - } - } - return 'plaintext' - } - - /** - * Форматирует XML/HTML с отступами - */ - function prettyFormatXML(xml: string): string { - let formatted = ''; - const reg = /(>)(<)(\/*)/g; - xml = xml.replace(reg, '$1\r\n$2$3'); - let pad = 0; - xml.split('\r\n').forEach((node) => { - let indent = 0; - if (node.match(/.+<\/\w[^>]*>$/)) { - indent = 0; - } else if (node.match(/^<\//)) { - if (pad !== 0) pad -= 2; - } else if (node.match(/^<\w([^>]*[^/])?>.*$/)) { - indent = 2; - } else { - indent = 0; - } - formatted += ' '.repeat(pad) + node + '\r\n'; - pad += indent; - }); - return formatted.trim(); - } - - /** - * Форматирует и подсвечивает код - */ - function formatCode(content: string): string { - const language = detectLanguage(content) - - if (language === 'json') { - try { - // Форматируем JSON с отступами - const formatted = JSON.stringify(JSON.parse(content), null, 2) - return Prism.highlight(formatted, Prism.languages[language], language) - } catch { - return content - } - } else if (language === 'markup') { - // Форматируем XML/HTML с отступами - const formatted = prettyFormatXML(content) - return Prism.highlight(formatted, Prism.languages[language], language) - } - - return content - } - - /** - * Компонент модального окна для просмотра содержимого публикации - */ - const BodyModal: Component = () => { - const language = () => detectLanguage(selectedShoutBody()) - const formattedCode = () => formatCode(selectedShoutBody()) - - return ( - - - - ) - } - - /** - * Компонент модального окна для просмотра содержимого media.body - */ - const MediaBodyModal: Component = () => { - const language = () => detectLanguage(selectedMediaBody()) - const formattedCode = () => formatCode(selectedMediaBody()) - - return ( - - - - ) - } - - /** - * Обработчик изменения страницы для публикаций - * @param page - Номер страницы - */ - function handleShoutsPageChange(page: number) { - setShoutsPagination({ ...shoutsPagination(), page }) - loadShouts() - } - - /** - * Обработчик изменения количества публикаций на странице - * @param limit - Количество элементов - */ - function handleShoutsPerPageChange(limit: number) { - setShoutsPagination({ ...shoutsPagination(), page: 1, limit }) - loadShouts() - } - - /** - * Компонент пагинации для публикаций - */ - const ShoutsPagination: Component = () => { - const pagination = shoutsPagination() - const totalPages = pagination.totalPages - const currentPage = pagination.page - - // Генерируем массив страниц для отображения - const pages = [] - const maxVisiblePages = 5 // Максимальное количество видимых страниц - - // Всегда показываем первую страницу - pages.push(1) - - // Вычисляем диапазон страниц вокруг текущей - let startPage = Math.max(2, currentPage - Math.floor(maxVisiblePages / 2)) - let endPage = Math.min(totalPages - 1, startPage + maxVisiblePages - 2) - - // Корректируем диапазон, если он выходит за границы - if (endPage - startPage < maxVisiblePages - 2) { - startPage = Math.max(2, endPage - maxVisiblePages + 2) - } - - // Добавляем многоточие после первой страницы, если нужно - if (startPage > 2) { - pages.push('...') - } - - // Добавляем страницы из диапазона - for (let i = startPage; i <= endPage; i++) { - pages.push(i) - } - - // Добавляем многоточие перед последней страницей, если нужно - if (endPage < totalPages - 1) { - pages.push('...') - } - - // Всегда показываем последнюю страницу, если есть больше одной страницы - if (totalPages > 1) { - pages.push(totalPages) - } - - return ( - - ) + const handleSuccess = (message: string) => { + setSuccessMessage(message) + // Скрываем сообщение через 3 секунды + setTimeout(() => setSuccessMessage(null), 3000) } return ( -
+
-
-

Панель администратора

-
-
-
{error()}
+
{error()}
-
{successMessage()}
+
{successMessage()}
- - -
Загрузка данных...
-
- - -
Нет данных для отображения
-
- - 0}> -
-
-
- - -
-
-
- -
- - - - - - - - - - - - - {(user) => ( - - - - - - - - )} - - -
IDEmailИмяСозданРоли
{user.id}{user.email}{user.name || '-'}{formatDateRelative(user.created_at)} -
- - {(role) => } - -
{ - setSelectedUser(user) - setShowRolesModal(true) - }} - > - 🎭 -
-
-
-
- - -
+ {/* Используем Show компоненты для каждой вкладки */} + + - -
Загрузка публикаций...
-
+ +
- -
Нет публикаций для отображения
-
+ + + - 0}> -
-
-
- setShoutsSearchQuery(e.currentTarget.value)} - onKeyDown={(e) => { - if (e.key === 'Enter') { - loadShouts() - } - }} - class="search-input" - /> - -
-
- -
- -
-
- -
- - - - - - - - - - - - - - - - - {(shout) => ( - - - - - - - - - - - - )} - - -
IDЗаголовокSlugСтатусАвторыТемыСозданСодержимоеMedia
{shout.id}{truncateText(shout.title, 50)}{truncateText(shout.slug, 30)} - - {getShoutStatus(shout)} - - - 0}> -
- - {(author) => ( - - {author.name || author.email || `ID:${author.id}`} - - )} - -
-
- - - - -
- 0}> -
- - {(topic) => ( - - {topic.title || topic.slug} - - )} - -
-
- - - - -
{formatDateRelative(shout.created_at)} { - setSelectedShoutBody(shout.body) - setShowBodyModal(true) - }} - style="cursor: pointer; max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" - > - {truncateText(shout.body.replace(/<[^>]*>/g, ''), 100)} - - 0}> -
- - {(mediaItem, idx) => ( -
- {mediaItem.title || `media[${idx()}]`} - - - -
- )} -
-
-
- - - - -
- -
-
+ + - +
- - - - - - - - - - -
) } diff --git a/panel/discours.svg b/panel/assets/discours.svg similarity index 100% rename from panel/discours.svg rename to panel/assets/discours.svg diff --git a/panel/publy.svg b/panel/assets/publy.svg similarity index 100% rename from panel/publy.svg rename to panel/assets/publy.svg diff --git a/panel/auth.ts b/panel/auth.ts deleted file mode 100644 index 70533217..00000000 --- a/panel/auth.ts +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Модуль авторизации - * @module auth - */ - -// Экспортируем константы для использования в других модулях -export const AUTH_TOKEN_KEY = 'auth_token' -export const CSRF_TOKEN_KEY = 'csrf_token' - -/** - * Интерфейс для учетных данных - */ -export interface Credentials { - email: string - password: string -} - -/** - * Интерфейс для результата авторизации - */ -export interface LoginResult { - success: boolean - token?: string - error?: string -} - -/** - * Интерфейс для ответа API при логине - */ -interface LoginResponse { - login: LoginResult -} - -/** - * Получает токен авторизации из cookie - * @returns Токен или пустую строку, если токен не найден - */ -export function getAuthTokenFromCookie(): string { - const cookieItems = document.cookie.split(';') - for (const item of cookieItems) { - const [name, value] = item.trim().split('=') - if (name === AUTH_TOKEN_KEY) { - return value - } - } - return '' -} - -/** - * Получает CSRF-токен из cookie - * @returns CSRF-токен или пустую строку, если токен не найден - */ -export function getCsrfTokenFromCookie(): string { - const cookieItems = document.cookie.split(';') - for (const item of cookieItems) { - const [name, value] = item.trim().split('=') - if (name === CSRF_TOKEN_KEY) { - return value - } - } - return '' -} - -/** - * Проверяет, авторизован ли пользователь - * @returns Статус авторизации - */ -export function isAuthenticated(): boolean { - // Проверяем наличие cookie auth_token - const cookieToken = getAuthTokenFromCookie() - const hasCookie = !!cookieToken && cookieToken.length > 10 - - // Проверяем наличие токена в localStorage - const localToken = localStorage.getItem(AUTH_TOKEN_KEY) - const hasLocalToken = !!localToken && localToken.length > 10 - - // Пользователь авторизован, если есть cookie или токен в localStorage - return hasCookie || hasLocalToken -} - -/** - * Выполняет выход из системы - * @param callback - Функция обратного вызова после выхода - */ -export function logout(callback?: () => void): void { - // Очищаем токен из localStorage - localStorage.removeItem(AUTH_TOKEN_KEY) - - // Для удаления cookie устанавливаем ей истекшее время жизни - document.cookie = `${AUTH_TOKEN_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;` - - // Дополнительно пытаемся сделать запрос на сервер для удаления серверных сессий - try { - fetch('/auth/logout', { - method: 'POST', // Используем POST вместо GET для операций изменения состояния - credentials: 'include', - headers: { - 'Content-Type': 'application/json', - 'X-CSRF-Token': getCsrfTokenFromCookie() // Добавляем CSRF токен если он есть - } - }).catch((e) => { - console.error('Ошибка при запросе на выход:', e) - }) - } catch (e) { - console.error('Ошибка при выходе:', e) - } - - // Вызываем функцию обратного вызова после очистки токенов - if (callback) callback() -} - -/** - * Выполняет вход в систему используя GraphQL-запрос - * @param credentials - Учетные данные - * @returns Результат авторизации - */ -export async function login(credentials: Credentials): Promise { - try { - console.log('Отправка запроса авторизации через GraphQL') - - const response = await fetch(`${location.origin}/graphql`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'X-CSRF-Token': getCsrfTokenFromCookie() // Добавляем CSRF токен если он есть - }, - credentials: 'include', // Важно для обработки cookies - body: JSON.stringify({ - query: ` - mutation Login($email: String!, $password: String!) { - login(email: $email, password: $password) { - success - token - error - } - } - `, - variables: { - email: credentials.email, - password: credentials.password - } - }) - }) - - if (!response.ok) { - const errorText = await response.text() - console.error('Ошибка HTTP:', response.status, errorText) - throw new Error(`HTTP error: ${response.status} ${response.statusText}`) - } - - const result = await response.json() - console.log('Результат авторизации:', result) - - if (result?.data?.login?.success) { - // Проверяем, установил ли сервер cookie - const cookieToken = getAuthTokenFromCookie() - const hasCookie = !!cookieToken && cookieToken.length > 10 - - // Если cookie не установлена, но есть токен в ответе, сохраняем его в localStorage - if (!hasCookie && result.data.login.token) { - localStorage.setItem(AUTH_TOKEN_KEY, result.data.login.token) - } - - return true - } - - if (result.errors && result.errors.length > 0) { - throw new Error(result.errors[0].message || 'Ошибка авторизации') - } - - throw new Error(result?.data?.login?.error || 'Неизвестная ошибка авторизации') - } catch (error) { - console.error('Ошибка при входе:', error) - throw error - } -} diff --git a/panel/context/auth.tsx b/panel/context/auth.tsx new file mode 100644 index 00000000..e0c896b7 --- /dev/null +++ b/panel/context/auth.tsx @@ -0,0 +1,150 @@ +import { Component, createContext, createSignal, JSX, useContext } from 'solid-js' +import { query } from '../graphql' +import { ADMIN_LOGIN_MUTATION, ADMIN_LOGOUT_MUTATION } from '../graphql/mutations' +import { + AUTH_TOKEN_KEY, + CSRF_TOKEN_KEY, + checkAuthStatus, + clearAuthTokens, + getAuthTokenFromCookie, + getCsrfTokenFromCookie, + saveAuthToken +} from '../utils/auth' +/** + * Модуль авторизации + * @module auth + */ + +/** + * Интерфейс для учетных данных + */ +export interface Credentials { + email: string + password: string +} + +/** + * Интерфейс для результата авторизации + */ +export interface LoginResult { + success: boolean + token?: string + error?: string +} + +// Экспортируем утилитарные функции для обратной совместимости +export { + AUTH_TOKEN_KEY, + CSRF_TOKEN_KEY, + getAuthTokenFromCookie, + getCsrfTokenFromCookie, + checkAuthStatus, + clearAuthTokens, + saveAuthToken +} + +interface AuthContextType { + isAuthenticated: () => boolean + login: (username: string, password: string) => Promise + logout: () => Promise +} + +const AuthContext = createContext({ + isAuthenticated: () => false, + login: async () => {}, + logout: async () => {} +}) + +export const useAuth = () => useContext(AuthContext) + +interface AuthProviderProps { + children: JSX.Element +} + +export const AuthProvider: Component = (props) => { + console.log('[AuthProvider] Initializing...') + const [isAuthenticated, setIsAuthenticated] = createSignal(checkAuthStatus()) + console.log( + `[AuthProvider] Initial auth state: ${isAuthenticated() ? 'authenticated' : 'not authenticated'}` + ) + + const login = async (username: string, password: string) => { + console.log('[AuthProvider] Attempting login...') + try { + const result = await query<{ login: { success: boolean; token?: string } }>( + `${location.origin}/graphql`, + ADMIN_LOGIN_MUTATION, + { email: username, password } + ) + + if (result?.login?.success) { + console.log('[AuthProvider] Login successful') + if (result.login.token) { + saveAuthToken(result.login.token) + } + setIsAuthenticated(true) + // Убираем window.location.href - пусть роутер сам обрабатывает навигацию + } else { + console.error('[AuthProvider] Login failed') + throw new Error('Неверные учетные данные') + } + } catch (error) { + console.error('[AuthProvider] Login error:', error) + throw error + } + } + + const logout = async () => { + console.log('[AuthProvider] Attempting logout...') + try { + const result = await query<{ logout: { success: boolean } }>( + `${location.origin}/graphql`, + ADMIN_LOGOUT_MUTATION + ) + + if (result?.logout?.success) { + console.log('[AuthProvider] Logout successful') + clearAuthTokens() + setIsAuthenticated(false) + window.location.href = '/login' + } + } catch (error) { + console.error('[AuthProvider] Logout error:', error) + // Даже при ошибке очищаем токены и редиректим + clearAuthTokens() + setIsAuthenticated(false) + window.location.href = '/login' + } + } + + const value: AuthContextType = { + isAuthenticated, + login, + logout + } + + console.log('[AuthProvider] Rendering provider with context') + return {props.children} +} + +// Export the logout function for direct use +export const logout = async () => { + console.log('[Auth] Executing standalone logout...') + try { + const result = await query<{ logout: { success: boolean } }>( + `${location.origin}/graphql`, + ADMIN_LOGOUT_MUTATION + ) + console.log('[Auth] Standalone logout result:', result) + if (result?.logout?.success) { + clearAuthTokens() + return true + } + return false + } catch (error) { + console.error('[Auth] Standalone logout error:', error) + // Даже при ошибке очищаем токены + clearAuthTokens() + throw error + } +} diff --git a/panel/graphql.ts b/panel/graphql.ts deleted file mode 100644 index 5f8c87e1..00000000 --- a/panel/graphql.ts +++ /dev/null @@ -1,208 +0,0 @@ -/** - * API-клиент для работы с GraphQL - * @module api - */ - -import { AUTH_TOKEN_KEY, CSRF_TOKEN_KEY, getAuthTokenFromCookie, getCsrfTokenFromCookie } from './auth' - -/** - * Тип для произвольных данных GraphQL - */ -type GraphQLData = Record - -/** - * Обрабатывает ошибки от API - * @param response - Ответ от сервера - * @returns Обработанный текст ошибки - */ -async function handleApiError(response: Response): Promise { - try { - const contentType = response.headers.get('content-type') - - if (contentType?.includes('application/json')) { - const errorData = await response.json() - - // Проверяем GraphQL ошибки - if (errorData.errors && errorData.errors.length > 0) { - return errorData.errors[0].message - } - - // Проверяем сообщение об ошибке - if (errorData.error || errorData.message) { - return errorData.error || errorData.message - } - } - - // Если не JSON или нет структурированной ошибки, читаем как текст - const errorText = await response.text() - return `Ошибка сервера: ${response.status} ${response.statusText}. ${errorText.substring(0, 100)}...` - } catch (_e) { - // Если не можем прочитать ответ - return `Ошибка сервера: ${response.status} ${response.statusText}` - } -} - -/** - * Проверяет наличие ошибок авторизации в ответе GraphQL - * @param errors - Массив ошибок GraphQL - * @returns true если есть ошибки авторизации - */ -function hasAuthErrors(errors: Array<{ message?: string; extensions?: { code?: string } }>): boolean { - return errors.some( - (error) => - (error.message && - (error.message.toLowerCase().includes('unauthorized') || - error.message.toLowerCase().includes('авторизации') || - error.message.toLowerCase().includes('authentication') || - error.message.toLowerCase().includes('unauthenticated') || - error.message.toLowerCase().includes('token'))) || - error.extensions?.code === 'UNAUTHENTICATED' || - error.extensions?.code === 'FORBIDDEN' - ) -} - -/** - * Подготавливает URL для GraphQL запроса - * @param url - URL или путь для запроса - * @returns Полный URL для запроса - */ -function prepareUrl(url: string): string { - // В режиме локальной разработки всегда используем /graphql - if (location.hostname === 'localhost') { - return `${location.origin}/graphql` - } - - // Если это относительный путь, добавляем к нему origin - if (url.startsWith('/')) { - return `${location.origin}${url}` - } - // Если это уже полный URL, используем как есть - return url -} - -/** - * Возвращает заголовки для GraphQL запроса с учетом авторизации и CSRF - * @returns Объект с заголовками - */ -function getRequestHeaders(): Record { - const headers: Record = { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - } - - // Проверяем наличие токена в localStorage - const localToken = localStorage.getItem(AUTH_TOKEN_KEY) - - // Проверяем наличие токена в cookie - const cookieToken = getAuthTokenFromCookie() - - // Используем токен из localStorage или cookie - const token = localToken || cookieToken - - // Если есть токен, добавляем его в заголовок Authorization с префиксом Bearer - if (token && token.length > 10) { - headers['Authorization'] = `Bearer ${token}` - console.debug('Отправка запроса с токеном авторизации') - } - - // Добавляем CSRF-токен, если он есть - const csrfToken = getCsrfTokenFromCookie() - if (csrfToken) { - headers['X-CSRF-Token'] = csrfToken - console.debug('Добавлен CSRF-токен в запрос') - } - - return headers -} - -/** - * Выполняет GraphQL запрос - * @param url - URL для запроса - * @param query - GraphQL запрос - * @param variables - Переменные запроса - * @returns Результат запроса - */ -export async function query( - url: string, - query: string, - variables: Record = {} -): Promise { - try { - // Получаем все необходимые заголовки для запроса - const headers = getRequestHeaders() - - // Подготавливаем полный URL - const fullUrl = prepareUrl(url) - console.debug('Отправка GraphQL запроса на:', fullUrl) - - const response = await fetch(fullUrl, { - method: 'POST', - headers, - // Важно: credentials: 'include' - для передачи cookies с запросом - credentials: 'include', - body: JSON.stringify({ - query, - variables - }) - }) - - // Проверяем статус ответа - if (!response.ok) { - const errorMessage = await handleApiError(response) - console.error('Ошибка API:', { - status: response.status, - statusText: response.statusText, - error: errorMessage - }) - - // Если получен 401 Unauthorized или 403 Forbidden, перенаправляем на страницу входа - if (response.status === 401 || response.status === 403) { - localStorage.removeItem(AUTH_TOKEN_KEY) - window.location.href = '/' - throw new Error('Unauthorized') - } - - throw new Error(errorMessage) - } - - // Проверяем, что ответ содержит JSON - const contentType = response.headers.get('content-type') - if (!contentType?.includes('application/json')) { - const text = await response.text() - throw new Error(`Неверный формат ответа: ${text.substring(0, 100)}...`) - } - - const result = await response.json() - - if (result.errors) { - // Проверяем ошибки на признаки проблем с авторизацией - if (hasAuthErrors(result.errors)) { - localStorage.removeItem(AUTH_TOKEN_KEY) - window.location.href = '/' - throw new Error('Unauthorized') - } - - throw new Error(result.errors[0].message) - } - - return result.data as T - } catch (error) { - console.error('API Error:', error) - throw error - } -} - -/** - * Выполняет GraphQL мутацию - * @param url - URL для запроса - * @param mutation - GraphQL мутация - * @param variables - Переменные мутации - * @returns Результат мутации - */ -export function mutate( - url: string, - mutation: string, - variables: Record = {} -): Promise { - return query(url, mutation, variables) -} diff --git a/panel/graphql/index.ts b/panel/graphql/index.ts new file mode 100644 index 00000000..d1b06d69 --- /dev/null +++ b/panel/graphql/index.ts @@ -0,0 +1,139 @@ +/** + * API-клиент для работы с GraphQL + * @module api + */ + +import { + AUTH_TOKEN_KEY, + clearAuthTokens, + getAuthTokenFromCookie, + getCsrfTokenFromCookie +} from '../utils/auth' + +/** + * Тип для произвольных данных GraphQL + */ +type GraphQLData = Record + +/** + * Возвращает заголовки для GraphQL запроса с учетом авторизации и CSRF + * @returns Объект с заголовками + */ +function getRequestHeaders(): Record { + const headers: Record = { + 'Content-Type': 'application/json', + Accept: 'application/json' + } + + // Проверяем наличие токена в localStorage + const localToken = localStorage.getItem(AUTH_TOKEN_KEY) + + // Проверяем наличие токена в cookie + const cookieToken = getAuthTokenFromCookie() + + // Используем токен из localStorage или cookie + const token = localToken || cookieToken + + // Если есть токен, добавляем его в заголовок Authorization с префиксом Bearer + if (token && token.length > 10) { + headers['Authorization'] = `Bearer ${token}` + console.debug('Отправка запроса с токеном авторизации') + } + + // Добавляем CSRF-токен, если он есть + const csrfToken = getCsrfTokenFromCookie() + if (csrfToken) { + headers['X-CSRF-Token'] = csrfToken + console.debug('Добавлен CSRF-токен в запрос') + } + + return headers +} + +/** + * Выполняет GraphQL запрос + * @param endpoint - URL эндпоинта GraphQL + * @param query - GraphQL запрос + * @param variables - Переменные запроса + * @returns Результат запроса + */ +export async function query( + endpoint: string, + query: string, + variables?: Record +): Promise { + try { + console.log(`[GraphQL] Making request to ${endpoint}`) + console.log(`[GraphQL] Query: ${query.substring(0, 100)}...`) + + const response = await fetch(endpoint, { + method: 'POST', + headers: getRequestHeaders(), + credentials: 'include', + body: JSON.stringify({ + query, + variables + }) + }) + + console.log(`[GraphQL] Response status: ${response.status}`) + + if (!response.ok) { + if (response.status === 401) { + console.log('[GraphQL] Unauthorized response, clearing auth tokens') + clearAuthTokens() + // Перенаправляем на страницу входа только если мы не на ней + if (!window.location.pathname.includes('/login')) { + window.location.href = '/login' + } + } + const errorText = await response.text() + throw new Error(`HTTP error: ${response.status} ${errorText}`) + } + + const result = await response.json() + console.log('[GraphQL] Response received:', result) + + if (result.errors) { + // Проверяем ошибки авторизации + const hasUnauthorized = result.errors.some( + (error: { message?: string }) => + error.message?.toLowerCase().includes('unauthorized') || + error.message?.toLowerCase().includes('please login') + ) + + if (hasUnauthorized) { + console.log('[GraphQL] Unauthorized error in response, clearing auth tokens') + clearAuthTokens() + // Перенаправляем на страницу входа только если мы не на ней + if (!window.location.pathname.includes('/login')) { + window.location.href = '/login' + } + } + + // Handle GraphQL errors + const errorMessage = result.errors.map((e: { message?: string }) => e.message).join(', ') + throw new Error(`GraphQL error: ${errorMessage}`) + } + + return result.data + } catch (error) { + console.error('[GraphQL] Query error:', error) + throw error + } +} + +/** + * Выполняет GraphQL мутацию + * @param url - URL для запроса + * @param mutation - GraphQL мутация + * @param variables - Переменные мутации + * @returns Результат мутации + */ +export function mutate( + url: string, + mutation: string, + variables: Record = {} +): Promise { + return query(url, mutation, variables) +} diff --git a/panel/graphql/mutations.ts b/panel/graphql/mutations.ts new file mode 100644 index 00000000..063df94c --- /dev/null +++ b/panel/graphql/mutations.ts @@ -0,0 +1,63 @@ +export const ADMIN_LOGIN_MUTATION = ` + mutation AdminLogin($email: String!, $password: String!) { + login(email: $email, password: $password) { + success + token + } + } +` + +export const ADMIN_LOGOUT_MUTATION = ` + mutation AdminLogout { + logout { + success + } + } +` + +export const ADMIN_UPDATE_USER_MUTATION = ` + mutation AdminUpdateUser($user: AdminUserUpdateInput!) { + adminUpdateUser(user: $user) { + success + error + } + } +` + +export const ADMIN_UPDATE_ENV_VARIABLE_MUTATION = ` + mutation AdminUpdateEnvVariable($key: String!, $value: String!) { + updateEnvVariable(key: $key, value: $value) + } +` + +export const UPDATE_TOPIC_MUTATION = ` + mutation UpdateTopic($topic_input: TopicInput!) { + update_topic(topic_input: $topic_input) { + error + } + } +` + +export const DELETE_TOPIC_MUTATION = ` + mutation DeleteTopic($id: Int!) { + delete_topic_by_id(id: $id) { + error + } + } +` + +export const UPDATE_COMMUNITY_MUTATION = ` + mutation UpdateCommunity($community_input: CommunityInput!) { + update_community(community_input: $community_input) { + error + } + } +` + +export const DELETE_COMMUNITY_MUTATION = ` + mutation DeleteCommunity($slug: String!) { + delete_community(slug: $slug) { + error + } + } +` diff --git a/panel/graphql/queries.ts b/panel/graphql/queries.ts new file mode 100644 index 00000000..0236f514 --- /dev/null +++ b/panel/graphql/queries.ts @@ -0,0 +1,156 @@ +import { gql } from 'graphql-tag' + +// Определяем GraphQL запрос +export const ADMIN_GET_SHOUTS_QUERY: string = + gql` + query AdminGetShouts($limit: Int, $offset: Int, $search: String, $status: String) { + adminGetShouts(limit: $limit, offset: $offset, search: $search, status: $status) { + shouts { + id + title + slug + body + lead + subtitle + layout + lang + cover + cover_caption + media { + url + title + body + source + pic + date + genre + artist + lyrics + } + seo + created_at + updated_at + published_at + featured_at + deleted_at + created_by { + id + email + name + } + authors { + id + name + email + } + topics { + id + title + slug + } + stat { + rating + comments_count + viewed + } + } + total + page + perPage + totalPages + } + } +`.loc?.source.body || '' + +export const ADMIN_GET_USERS_QUERY: string = + gql` + query AdminGetUsers($limit: Int, $offset: Int, $search: String) { + adminGetUsers(limit: $limit, offset: $offset, search: $search) { + authors { + id + email + name + slug + roles + created_at + last_seen + } + total + page + perPage + totalPages + } + } +`.loc?.source.body || '' + +export const ADMIN_GET_ROLES_QUERY: string = + gql` + query AdminGetRoles { + adminGetRoles { + id + name + description + } + } +`.loc?.source.body || '' + +export const ADMIN_GET_ENV_VARIABLES_QUERY: string = + gql` + query GetEnvVariables { + getEnvVariables { + name + description + variables { + key + value + description + type + isSecret + } + } + } +`.loc?.source.body || '' + +export const GET_COMMUNITIES_QUERY: string = + gql` + query GetCommunities { + get_communities_all { + id + slug + name + desc + pic + created_at + created_by { + id + name + email + } + stat { + shouts + followers + authors + } + } + } +`.loc?.source.body || '' + +export const GET_TOPICS_QUERY: string = + gql` + query GetTopics { + get_topics_all { + id + slug + title + body + pic + community + parent_ids + stat { + shouts + authors + followers + } + } + } +`.loc?.source.body || '' diff --git a/panel/login.tsx b/panel/login.tsx deleted file mode 100644 index e39e731c..00000000 --- a/panel/login.tsx +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Компонент страницы входа - * @module LoginPage - */ - -import { Component, createSignal } from 'solid-js' -import { login } from './auth' -import logo from './publy.svg' - -interface LoginPageProps { - onLoginSuccess?: () => void -} - -/** - * Компонент страницы входа - */ -const LoginPage: Component = (props) => { - const [email, setEmail] = createSignal('') - const [password, setPassword] = createSignal('') - const [isLoading, setIsLoading] = createSignal(false) - const [error, setError] = createSignal(null) - const [formSubmitting, setFormSubmitting] = createSignal(false) - - /** - * Обработчик отправки формы входа - * @param e - Событие отправки формы - */ - const handleSubmit = async (e: Event) => { - e.preventDefault() - - // Предотвращаем повторную отправку формы - if (formSubmitting()) return - - // Очищаем пробелы в email - const cleanEmail = email().trim() - - if (!cleanEmail || !password()) { - setError('Пожалуйста, заполните все поля') - return - } - - setFormSubmitting(true) - setIsLoading(true) - setError(null) - - try { - // Используем функцию login из модуля auth - const loginSuccessful = await login({ - email: cleanEmail, - password: password() - }) - - if (loginSuccessful) { - // Вызываем коллбэк для оповещения родителя об успешном входе - if (props.onLoginSuccess) { - props.onLoginSuccess() - } - } else { - throw new Error('Вход не выполнен') - } - } catch (err) { - console.error('Ошибка при входе:', err) - setError(err instanceof Error ? err.message : 'Неизвестная ошибка') - setIsLoading(false) - } finally { - setFormSubmitting(false) - } - } - - return ( - - ) -} - -export default LoginPage diff --git a/panel/modals/EnvVariableModal.tsx b/panel/modals/EnvVariableModal.tsx new file mode 100644 index 00000000..636e2871 --- /dev/null +++ b/panel/modals/EnvVariableModal.tsx @@ -0,0 +1,188 @@ +import { Component, createMemo, createSignal, Show } from 'solid-js' +import { query } from '../graphql' +import { EnvVariable } from '../graphql/generated/schema' +import { ADMIN_UPDATE_ENV_VARIABLE_MUTATION } from '../graphql/mutations' +import formStyles from '../styles/Form.module.css' +import Button from '../ui/Button' +import Modal from '../ui/Modal' +import TextPreview from '../ui/TextPreview' + +interface EnvVariableModalProps { + isOpen: boolean + variable: EnvVariable + onClose: () => void + onSave: () => void + onValueChange?: (value: string) => void // FIXME: no need +} + +const EnvVariableModal: Component = (props) => { + const [value, setValue] = createSignal(props.variable.value) + const [saving, setSaving] = createSignal(false) + const [error, setError] = createSignal(null) + const [showFormatted, setShowFormatted] = createSignal(false) + + // Определяем нужно ли использовать textarea + const needsTextarea = createMemo(() => { + const val = value() + return ( + val.length > 50 || + val.includes('\n') || + props.variable.type === 'json' || + props.variable.key.includes('URL') || + props.variable.key.includes('SECRET') + ) + }) + + // Форматируем JSON если возможно + const formattedValue = createMemo(() => { + if (props.variable.type === 'json' || (value().startsWith('{') && value().endsWith('}'))) { + try { + return JSON.stringify(JSON.parse(value()), null, 2) + } catch { + return value() + } + } + return value() + }) + + const handleSave = async () => { + setSaving(true) + setError(null) + + try { + const result = await query<{ updateEnvVariable: boolean }>( + `${location.origin}/graphql`, + ADMIN_UPDATE_ENV_VARIABLE_MUTATION, + { + key: props.variable.key, + value: value() + } + ) + + if (result?.updateEnvVariable) { + props.onSave() + } else { + setError('Failed to update environment variable') + } + } catch (err) { + setError(err instanceof Error ? err.message : 'Unknown error occurred') + } finally { + setSaving(false) + } + } + + const formatValue = () => { + if (props.variable.type === 'json') { + try { + const formatted = JSON.stringify(JSON.parse(value()), null, 2) + setValue(formatted) + } catch (_e) { + setError('Invalid JSON format') + } + } + } + + return ( + +
+
e.preventDefault()}> +
+ + +
+ +
+ + + +
+