diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 22b8f61..8e79ff7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,7 @@ jobs: echo "EMAIL_GRAPHQL=fake@example.com" >> .env echo "NEXTAUTH_SECRET=fakesecret" >> .env echo "BOT_URL=http://localhost:3000" >> .env + echo "REDIS_PASSWORD=fake" > .env - name: Set image tags id: vars @@ -83,6 +84,7 @@ jobs: echo "WEB_IMAGE_TAG=${{ needs.build-and-push.outputs.web_tag }}" >> .env echo "BOT_IMAGE_TAG=${{ needs.build-and-push.outputs.bot_tag }}" >> .env echo "DOCKERHUB_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}" >> .env + echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}" >> .env - name: Copy .env to VPS via SCP uses: appleboy/scp-action@master diff --git a/apps/bot/eslint.config.js b/apps/bot/eslint.config.js index fe052f3..f19765f 100644 --- a/apps/bot/eslint.config.js +++ b/apps/bot/eslint.config.js @@ -5,5 +5,10 @@ export default [ ...typescript, { ignores: ['**/types/**', '*.config.*'], + rules: { + '@typescript-eslint/naming-convention': 'off', + 'unicorn/prevent-abbreviations': 'off', + 'canonical/id-match': 'off', + }, }, ]; diff --git a/apps/bot/locales/ru.ftl b/apps/bot/locales/ru.ftl new file mode 100644 index 0000000..a663c8b --- /dev/null +++ b/apps/bot/locales/ru.ftl @@ -0,0 +1,105 @@ +# Описание бота +short-description = + Запись к мастерам, тренерам и репетиторам на вашем смартфоне 📱📅 + + ℹ️ По всем вопросам и обратной связи: @vchikalkin + +description = + 📲 Запишись.онлайн — это бесплатное Telegram-приложение для мастеров и тренеров в вашем смартфоне. + + Возможности: + • 📅 Ведение графика и запись клиентов + • 👥 Клиентская база в одном месте + • 🔔 Уведомления о новых и предстоящих записях + • 🧑‍ Работа мастером или тренером прямо в Telegram + • 🚀 Создание записи на услугу в пару кликов + + ✨ Всё, что нужно — ваш смартфон. + + + ℹ️ По всем вопросам и обратной связи: @vchikalkin + +# Команды +start = + .description = Запуск бота +addcontact = + .description = Добавить контакт клиента +becomemaster = + .description = Стать мастером +sharebot = + .description = Поделиться ботом +help = + .description = Список команд и поддержка + +commands-list = + 📋 Доступные команды: + • /addcontact — добавить контакт клиента + • /becomemaster — стать мастером + • /sharebot — поделиться ботом + • /help — список команд + + Откройте приложение кнопкой "Открыть", чтобы отредактировать свой профиль или создать запись + +support = + ℹ️ По всем вопросам и обратной связи: @vchikalkin + + +# Приветственные сообщения +msg-welcome = + 👋 Добро пожаловать! + Пожалуйста, поделитесь своим номером телефона для регистрации + +msg-welcome-back = 👋 С возвращением, { $name }! + +# Сообщения о статусе мастера +msg-not-master = + ⛔️ Только мастер может добавлять контакты + Стать мастером можно на странице профиля в приложении или с помощью команды /becomemaster + +msg-already-master = 🎉 Вы уже являетесь мастером! + +msg-become-master = 🥳 Поздравляем! Теперь вы мастер + +# Сообщения о телефоне +msg-need-phone = 📱 Чтобы добавить контакт, сначала поделитесь своим номером телефона + +msg-phone-saved = + ✅ Спасибо! Мы сохранили ваш номер телефона + Теперь вы можете открыть приложение или воспользоваться командами бота + +msg-already-registered = + ✅ Вы уже зарегистрированы в системе + + Для смены номера телефона обратитесь в поддержку (Контакты в профиле бота) + +msg-invalid-phone = ❌ Некорректный номер телефона + +# Сообщения о контактах +msg-send-client-contact = + 👤 Отправьте контакт клиента, которого вы хотите добавить. + Для отмены операции используйте команду /cancel + +msg-send-contact = Пожалуйста, отправьте контакт клиента через кнопку Telegram + +msg-contact-added = + ✅ Добавили { $name } в список ваших клиентов + + Пригласите клиента в приложение, чтобы вы могли добавлять с ним записи + +msg-contact-forward = Перешлите пользователю следующее сообщение, чтобы он мог начать пользоваться ботом ⬇️ + +# Сообщения для шаринга +msg-share-bot = + 📅 Воспользуйтесь этим ботом для записи к вашему мастеру! + Нажмите кнопку ниже, чтобы начать + +# Системные сообщения +msg-cancel = ❌ Операция отменена +msg-unhandled = ❓ Неизвестная команда. Попробуйте /start + +# Ошибки +err-generic = ⚠️ Что-то пошло не так. Попробуйте еще раз через несколько секунд +err-banned = 🚫 Ваш аккаунт заблокирован +err-with-details = ❌ Произошла ошибка +{ $error } +err-limit-exceeded = 🚫 Слишком много запросов! Подождите немного \ No newline at end of file diff --git a/apps/bot/package.json b/apps/bot/package.json index 1e1bc96..723aa97 100644 --- a/apps/bot/package.json +++ b/apps/bot/package.json @@ -12,10 +12,23 @@ "lint-staged": "lint-staged" }, "dependencies": { + "@grammyjs/auto-chat-action": "^0.1.1", + "@grammyjs/commands": "^1.2.0", + "@grammyjs/conversations": "^2.1.0", + "@grammyjs/hydrate": "^1.6.0", + "@grammyjs/i18n": "^1.1.2", + "@grammyjs/parse-mode": "^2.2.0", + "@grammyjs/ratelimiter": "^1.2.1", + "@grammyjs/runner": "^2.0.3", + "@grammyjs/storage-redis": "^2.5.1", + "@grammyjs/types": "^3.22.1", "@repo/graphql": "workspace:*", "@repo/typescript-config": "workspace:*", "@types/node": "catalog:", - "telegraf": "catalog:", + "grammy": "^1.38.1", + "ioredis": "^5.7.0", + "pino": "^9.9.0", + "pino-pretty": "^13.1.1", "tsup": "^8.5.0", "typescript": "catalog:", "zod": "catalog:" diff --git a/apps/bot/src/bot/context.ts b/apps/bot/src/bot/context.ts new file mode 100644 index 0000000..47816b0 --- /dev/null +++ b/apps/bot/src/bot/context.ts @@ -0,0 +1,21 @@ +import { type logger } from '@/utils/logger'; +import { type AutoChatActionFlavor } from '@grammyjs/auto-chat-action'; +import { type CommandsFlavor } from '@grammyjs/commands'; +import { type ConversationFlavor } from '@grammyjs/conversations'; +import { type HydrateFlavor } from '@grammyjs/hydrate'; +import { type I18nFlavor } from '@grammyjs/i18n'; +import { type Context as DefaultContext, type SessionFlavor } from 'grammy'; + +export type Context = ConversationFlavor< + HydrateFlavor< + AutoChatActionFlavor & + CommandsFlavor & + DefaultContext & + I18nFlavor & + SessionFlavor & { + logger: typeof logger; + } + > +>; + +export type SessionData = {}; diff --git a/apps/bot/src/bot/features/add-contact.ts b/apps/bot/src/bot/features/add-contact.ts new file mode 100644 index 0000000..1c1111b --- /dev/null +++ b/apps/bot/src/bot/features/add-contact.ts @@ -0,0 +1,101 @@ +/* eslint-disable id-length */ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { KEYBOARD_REMOVE, KEYBOARD_SHARE_BOT, KEYBOARD_SHARE_PHONE } from '@/config/keyboards'; +import { isCustomerMaster } from '@/utils/customer'; +import { isValidPhoneNumber, normalizePhoneNumber } from '@/utils/phone'; +import { type Conversation, createConversation } from '@grammyjs/conversations'; +import { CustomersService } from '@repo/graphql/api/customers'; +import { RegistrationService } from '@repo/graphql/api/registration'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +async function addContact(conversation: Conversation, ctx: Context) { + // Проверяем, что пользователь является мастером + const telegramId = ctx.from?.id; + if (!telegramId) { + return ctx.reply(await conversation.external(({ t }) => t('err-generic'))); + } + + const customerService = new CustomersService({ telegramId }); + const { customer } = await customerService.getCustomer({ telegramId }); + + if (!customer) { + return ctx.reply( + await conversation.external(({ t }) => t('msg-need-phone')), + KEYBOARD_SHARE_PHONE, + ); + } + + if (!isCustomerMaster(customer)) { + return ctx.reply(await conversation.external(({ t }) => t('msg-not-master'))); + } + + // Просим отправить контакт клиента + await ctx.reply(await conversation.external(({ t }) => t('msg-send-client-contact'))); + + // Ждем любое сообщение от пользователя + const waitCtx = await conversation.wait(); + + // Проверяем команду отмены + if (waitCtx.message?.text === '/cancel') { + return ctx.reply(await conversation.external(({ t }) => t('msg-cancel'))); + } + + // Проверяем, что отправлен контакт + if (!waitCtx.message?.contact) { + return ctx.reply(await conversation.external(({ t }) => t('msg-send-contact'))); + } + + const { contact } = waitCtx.message; + const name = `${contact.first_name || ''} ${contact.last_name || ''}`.trim(); + const phone = normalizePhoneNumber(contact.phone_number); + + // Проверяем валидность номера телефона + if (!isValidPhoneNumber(phone)) { + return ctx.reply(await conversation.external(({ t }) => t('msg-invalid-phone'))); + } + + try { + // Проверяем, есть ли клиент с таким номером + const { customer: existingCustomer } = await customerService.getCustomer({ phone }); + let documentId = existingCustomer?.documentId; + + // Если клиента нет, создаём нового + if (!documentId) { + const registrationService = new RegistrationService(); + const createCustomerResult = await registrationService.createCustomer({ name, phone }); + + documentId = createCustomerResult?.createCustomer?.documentId; + if (!documentId) throw new Error('Клиент не создан'); + } + + // Добавляем текущего мастера к клиенту + const masters = [customer.documentId]; + await customerService.addMasters({ data: { masters }, documentId }); + + // Отправляем подтверждения и инструкции + await ctx.reply(await conversation.external(({ t }) => t('msg-contact-added', { name }))); + await ctx.reply(await conversation.external(({ t }) => t('msg-contact-forward'))); + await ctx.reply(await conversation.external(({ t }) => t('msg-share-bot')), KEYBOARD_SHARE_BOT); + } catch (error) { + await ctx.reply( + await conversation.external(({ t }) => t('err-with-details', { error: String(error) })), + ); + } finally { + await ctx.reply(await conversation.external(({ t }) => t('commands-list')), KEYBOARD_REMOVE); + } + + return ctx.reply(await conversation.external(({ t }) => t('err-generic')), KEYBOARD_REMOVE); +} + +feature.use(createConversation(addContact)); + +feature.command('addcontact', logHandle('command-add-contact'), async (ctx) => { + await ctx.conversation.enter('addContact'); +}); + +export { composer as addContact }; diff --git a/apps/bot/src/bot/features/become-master.ts b/apps/bot/src/bot/features/become-master.ts new file mode 100644 index 0000000..1dbca9d --- /dev/null +++ b/apps/bot/src/bot/features/become-master.ts @@ -0,0 +1,42 @@ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { KEYBOARD_SHARE_PHONE } from '@/config/keyboards'; +import { isCustomerMaster } from '@/utils/customer'; +import { CustomersService } from '@repo/graphql/api/customers'; +import { Enum_Customer_Role } from '@repo/graphql/types'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +feature.command('becomemaster', logHandle('command-become-master'), async (ctx) => { + const telegramId = ctx.from.id; + const customerService = new CustomersService({ telegramId }); + const { customer } = await customerService.getCustomer({ telegramId }); + + if (!customer) { + return ctx.reply(ctx.t('msg-need-phone'), { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }); + } + + if (isCustomerMaster(customer)) { + return ctx.reply(ctx.t('msg-already-master'), { parse_mode: 'HTML' }); + } + + // Обновляем роль клиента на мастер + const response = await customerService + .updateCustomer({ + data: { role: Enum_Customer_Role.Master }, + }) + .catch((error) => { + ctx.reply(ctx.t('err-with-details', { error: String(error) }), { parse_mode: 'HTML' }); + }); + + if (response) { + return ctx.reply(ctx.t('msg-become-master'), { parse_mode: 'HTML' }); + } + + return ctx.reply(ctx.t('err-generic'), { parse_mode: 'HTML' }); +}); + +export { composer as becomeMaster }; diff --git a/apps/bot/src/bot/features/help.ts b/apps/bot/src/bot/features/help.ts new file mode 100644 index 0000000..70c9aad --- /dev/null +++ b/apps/bot/src/bot/features/help.ts @@ -0,0 +1,18 @@ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { KEYBOARD_REMOVE } from '@/config/keyboards'; +import { combine } from '@/utils/messages'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +feature.command('help', logHandle('command-help'), async (ctx) => { + return ctx.reply(combine(ctx.t('commands-list'), ctx.t('support')), { + ...KEYBOARD_REMOVE, + parse_mode: 'HTML', + }); +}); + +export { composer as help }; diff --git a/apps/bot/src/bot/features/index.ts b/apps/bot/src/bot/features/index.ts new file mode 100644 index 0000000..6caad36 --- /dev/null +++ b/apps/bot/src/bot/features/index.ts @@ -0,0 +1,6 @@ +export * from './add-contact'; +export * from './become-master'; +export * from './help'; +export * from './registration'; +export * from './share-bot'; +export * from './welcome'; diff --git a/apps/bot/src/bot/features/registration.ts b/apps/bot/src/bot/features/registration.ts new file mode 100644 index 0000000..745de66 --- /dev/null +++ b/apps/bot/src/bot/features/registration.ts @@ -0,0 +1,79 @@ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { KEYBOARD_REMOVE } from '@/config/keyboards'; +import { isValidPhoneNumber, normalizePhoneNumber } from '@/utils/phone'; +import { CustomersService } from '@repo/graphql/api/customers'; +import { RegistrationService } from '@repo/graphql/api/registration'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +// Обработка получения контакта от пользователя (регистрация или обновление) +feature.on(':contact', logHandle('contact-registration'), async (ctx) => { + const telegramId = ctx.from.id; + const { contact } = ctx.message; + const name = `${contact.first_name || ''} ${contact.last_name || ''}`.trim(); + + // Проверяем, не зарегистрирован ли уже пользователь + const customerService = new CustomersService({ telegramId }); + const { customer: existingCustomer } = await customerService.getCustomer({ telegramId }); + + if (existingCustomer) { + return ctx.reply(ctx.t('msg-already-registered'), { + ...KEYBOARD_REMOVE, + parse_mode: 'HTML', + }); + } + + // Проверка наличия номера телефона + if (!contact.phone_number) { + return ctx.reply(ctx.t('msg-invalid-phone')); + } + + // Нормализация и валидация номера + const phone = normalizePhoneNumber(contact.phone_number); + if (!isValidPhoneNumber(phone)) { + return ctx.reply(ctx.t('msg-invalid-phone')); + } + + const registrationService = new RegistrationService(); + + try { + const { customer } = await registrationService.getCustomer({ phone }); + + if (customer && !customer.telegramId) { + // Пользователь добавлен ранее мастером — обновляем данные + await registrationService.updateCustomer({ + data: { active: true, name, telegramId }, + documentId: customer.documentId, + }); + + return ctx.reply(ctx.t('msg-phone-saved') + '\n\n' + ctx.t('commands-list'), { + ...KEYBOARD_REMOVE, + parse_mode: 'HTML', + }); + } + + // Новый пользователь — создаём и активируем + const response = await registrationService.createCustomer({ name, phone, telegramId }); + + const documentId = response?.createCustomer?.documentId; + if (!documentId) return ctx.reply(ctx.t('err-generic')); + + await registrationService.updateCustomer({ + data: { active: true }, + documentId, + }); + + return ctx.reply(ctx.t('msg-phone-saved') + '\n\n' + ctx.t('commands-list'), { + ...KEYBOARD_REMOVE, + parse_mode: 'HTML', + }); + } catch (error) { + return ctx.reply(ctx.t('err-with-details', { error: String(error) })); + } +}); + +export { composer as registration }; diff --git a/apps/bot/src/bot/features/share-bot.ts b/apps/bot/src/bot/features/share-bot.ts new file mode 100644 index 0000000..d867ce5 --- /dev/null +++ b/apps/bot/src/bot/features/share-bot.ts @@ -0,0 +1,15 @@ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { KEYBOARD_SHARE_BOT } from '@/config/keyboards'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +feature.command('sharebot', logHandle('command-share-bot'), async (ctx) => { + await ctx.reply(ctx.t('msg-contact-forward'), { parse_mode: 'HTML' }); + await ctx.reply(ctx.t('msg-share-bot'), { ...KEYBOARD_SHARE_BOT, parse_mode: 'HTML' }); +}); + +export { composer as shareBot }; diff --git a/apps/bot/src/bot/features/unhandled.ts b/apps/bot/src/bot/features/unhandled.ts new file mode 100644 index 0000000..b376890 --- /dev/null +++ b/apps/bot/src/bot/features/unhandled.ts @@ -0,0 +1,17 @@ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +feature.on('message', logHandle('unhandled-message'), (ctx) => { + return ctx.reply(ctx.t('msg-unhandled')); +}); + +feature.on('callback_query', logHandle('unhandled-callback-query'), (ctx) => { + return ctx.answerCallbackQuery(); +}); + +export { composer as unhandledFeature }; diff --git a/apps/bot/src/bot/features/welcome.ts b/apps/bot/src/bot/features/welcome.ts new file mode 100644 index 0000000..da98597 --- /dev/null +++ b/apps/bot/src/bot/features/welcome.ts @@ -0,0 +1,33 @@ +import { type Context } from '@/bot/context'; +import { logHandle } from '@/bot/helpers/logging'; +import { KEYBOARD_REMOVE, KEYBOARD_SHARE_PHONE } from '@/config/keyboards'; +import { combine } from '@/utils/messages'; +import { CustomersService } from '@repo/graphql/api/customers'; +import { Composer } from 'grammy'; + +const composer = new Composer(); + +const feature = composer.chatType('private'); + +feature.command('start', logHandle('command-start'), async (ctx) => { + const telegramId = ctx.from.id; + + const customerService = new CustomersService({ telegramId }); + const { customer } = await customerService.getCustomer({ telegramId }); + + if (customer) { + // Пользователь уже зарегистрирован — приветствуем + return ctx.reply( + combine(ctx.t('msg-welcome-back', { name: customer.name }), ctx.t('commands-list')), + { + ...KEYBOARD_REMOVE, + parse_mode: 'HTML', + }, + ); + } + + // Новый пользователь — просим поделиться номером + return ctx.reply(ctx.t('msg-welcome'), { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }); +}); + +export { composer as welcome }; diff --git a/apps/bot/src/bot/handlers/errors.ts b/apps/bot/src/bot/handlers/errors.ts new file mode 100644 index 0000000..074f660 --- /dev/null +++ b/apps/bot/src/bot/handlers/errors.ts @@ -0,0 +1,18 @@ +import { type Context } from '../context'; +import { getUpdateInfo } from '../helpers/logging'; +import { KEYBOARD_REMOVE } from '@/config/keyboards'; +import { ERRORS } from '@repo/graphql/constants/errors'; +import { type ErrorHandler } from 'grammy'; + +export const errorHandler: ErrorHandler = async (error) => { + const { ctx } = error; + + const text = error.message.includes(ERRORS.NO_PERMISSION) ? 'err-banned' : 'err-generic'; + + await ctx.reply(ctx.t(text), { ...KEYBOARD_REMOVE, parse_mode: 'HTML' }); + + ctx.logger.error({ + err: error.error, + update: getUpdateInfo(ctx), + }); +}; diff --git a/apps/bot/src/bot/helpers/logging.ts b/apps/bot/src/bot/helpers/logging.ts new file mode 100644 index 0000000..dd7a651 --- /dev/null +++ b/apps/bot/src/bot/helpers/logging.ts @@ -0,0 +1,21 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { type Context } from '../context'; +import { type Update } from '@grammyjs/types'; +import { type Middleware } from 'grammy'; + +export function getUpdateInfo(context: Context): Omit { + const { update_id, ...update } = context.update; + + return update; +} + +export function logHandle(id: string): Middleware { + return (context, next) => { + context.logger.info({ + msg: `Handle "${id}"`, + ...(id.startsWith('unhandled') ? { update: getUpdateInfo(context) } : {}), + }); + + return next(); + }; +} diff --git a/apps/bot/src/bot/i18n.ts b/apps/bot/src/bot/i18n.ts new file mode 100644 index 0000000..d33ca01 --- /dev/null +++ b/apps/bot/src/bot/i18n.ts @@ -0,0 +1,14 @@ +import { type Context } from './context'; +import { I18n } from '@grammyjs/i18n'; +import path from 'node:path'; + +export const i18n = new I18n({ + defaultLocale: 'en', + directory: path.resolve(process.cwd(), 'locales'), + fluentBundleOptions: { + useIsolating: false, + }, + useSession: true, +}); + +export const isMultipleLocales = i18n.locales.length > 1; diff --git a/apps/bot/src/bot/index.ts b/apps/bot/src/bot/index.ts new file mode 100644 index 0000000..06f1b7e --- /dev/null +++ b/apps/bot/src/bot/index.ts @@ -0,0 +1,66 @@ +import { type Context } from './context'; +import * as features from './features'; +import { unhandledFeature } from './features/unhandled'; +import { errorHandler } from './handlers/errors'; +import { i18n } from './i18n'; +import * as middlewares from './middlewares'; +import { setCommands } from './settings/commands'; +import { setInfo } from './settings/info'; +import { env } from '@/config/env'; +import { logger } from '@/utils/logger'; +import { getRedisInstance } from '@/utils/redis'; +import { autoChatAction } from '@grammyjs/auto-chat-action'; +import { conversations } from '@grammyjs/conversations'; +import { hydrate } from '@grammyjs/hydrate'; +import { limit } from '@grammyjs/ratelimiter'; +import { Bot } from 'grammy'; + +type Parameters_ = { + token: string; +}; + +const redis = getRedisInstance(); + +export function createBot({ token }: Parameters_) { + const bot = new Bot(token); + + bot.use(i18n); + + bot.use( + limit({ + keyGenerator: (ctx) => ctx.from?.id.toString(), + limit: env.RATE_LIMIT, + onLimitExceeded: async (ctx) => { + await ctx.reply(ctx.t('err-limit-exceeded')); + }, + storageClient: redis, + timeFrame: env.RATE_LIMIT_TIME, + }), + ); + + bot.use(async (context, next) => { + context.logger = logger.child({ + update_id: context.update.update_id, + }); + await next(); + }); + + bot.use(conversations()); + + setInfo(bot); + setCommands(bot); + + const protectedBot = bot.errorBoundary(errorHandler); + + protectedBot.use(middlewares.updateLogger()); + protectedBot.use(autoChatAction(bot.api)); + protectedBot.use(hydrate()); + + for (const feature of Object.values(features)) { + protectedBot.use(feature); + } + + protectedBot.use(unhandledFeature); + + return bot; +} diff --git a/apps/bot/src/bot/middlewares/index.ts b/apps/bot/src/bot/middlewares/index.ts new file mode 100644 index 0000000..524b5f7 --- /dev/null +++ b/apps/bot/src/bot/middlewares/index.ts @@ -0,0 +1,2 @@ +export * from './session'; +export * from './update-logger'; diff --git a/apps/bot/src/bot/middlewares/session.ts b/apps/bot/src/bot/middlewares/session.ts new file mode 100644 index 0000000..209e6f6 --- /dev/null +++ b/apps/bot/src/bot/middlewares/session.ts @@ -0,0 +1,20 @@ +import { type Context } from '@/bot/context'; +import { TTL_SESSION } from '@/config/redis'; +import { getRedisInstance } from '@/utils/redis'; +import { getSessionKey } from '@/utils/session'; +import { RedisAdapter } from '@grammyjs/storage-redis'; +import { session as createSession, type Middleware } from 'grammy'; + +const storage = new RedisAdapter({ + autoParseDates: true, + instance: getRedisInstance(), + ttl: TTL_SESSION, +}); + +export function session(): Middleware { + return createSession({ + getSessionKey, + initial: () => ({}), + storage, + }); +} diff --git a/apps/bot/src/bot/middlewares/update-logger.ts b/apps/bot/src/bot/middlewares/update-logger.ts new file mode 100644 index 0000000..c3c6922 --- /dev/null +++ b/apps/bot/src/bot/middlewares/update-logger.ts @@ -0,0 +1,34 @@ +import { type Context } from '@/bot/context'; +import { getUpdateInfo } from '@/bot/helpers/logging'; +import { type Middleware } from 'grammy'; +import { performance } from 'node:perf_hooks'; + +export function updateLogger(): Middleware { + return async (ctx, next) => { + ctx.api.config.use((previous, method, payload, signal) => { + ctx.logger.debug({ + method, + msg: 'Bot API call', + payload, + }); + + return previous(method, payload, signal); + }); + + ctx.logger.debug({ + msg: 'Update received', + update: getUpdateInfo(ctx), + }); + + const startTime = performance.now(); + try { + return next(); + } finally { + const endTime = performance.now(); + ctx.logger.debug({ + elapsed: endTime - startTime, + msg: 'Update processed', + }); + } + }; +} diff --git a/apps/bot/src/bot/settings/commands.ts b/apps/bot/src/bot/settings/commands.ts new file mode 100644 index 0000000..dbd78ca --- /dev/null +++ b/apps/bot/src/bot/settings/commands.ts @@ -0,0 +1,39 @@ +import { type Context } from '@/bot/context'; +import { i18n } from '@/bot/i18n'; +import { Command, CommandGroup } from '@grammyjs/commands'; +import { type LanguageCode } from '@grammyjs/types'; +import { type Api, type Bot, type RawApi } from 'grammy'; + +export async function setCommands({ api }: Bot>) { + const commands = createCommands(['start', 'addcontact', 'becomemaster', 'sharebot', 'help']); + + for (const command of commands) { + addLocalizations(command); + } + + const commandsGroup = new CommandGroup().add(commands); + + await commandsGroup.setCommands({ api }); +} + +function addLocalizations(command: Command) { + for (const locale of i18n.locales) { + command.localize( + locale as LanguageCode, + command.name, + i18n.t(locale, `${command.name}.description`), + ); + } + + return command; +} + +function createCommand(name: string) { + return new Command(name, i18n.t('en', `${name}.description`)).addToScope({ + type: 'all_private_chats', + }); +} + +function createCommands(names: string[]) { + return names.map((name) => createCommand(name)); +} diff --git a/apps/bot/src/bot/settings/index.ts b/apps/bot/src/bot/settings/index.ts new file mode 100644 index 0000000..39fbc6b --- /dev/null +++ b/apps/bot/src/bot/settings/index.ts @@ -0,0 +1,2 @@ +export * from './commands'; +export * from './info'; diff --git a/apps/bot/src/bot/settings/info.ts b/apps/bot/src/bot/settings/info.ts new file mode 100644 index 0000000..0820b6d --- /dev/null +++ b/apps/bot/src/bot/settings/info.ts @@ -0,0 +1,10 @@ +import { type Context } from '../context'; +import { i18n } from '../i18n'; +import { type Api, type Bot, type RawApi } from 'grammy'; + +export async function setInfo({ api }: Bot>) { + for (const locale of i18n.locales) { + await api.setMyDescription(i18n.t(locale, 'description')); + await api.setMyShortDescription(i18n.t(locale, 'short-description')); + } +} diff --git a/apps/bot/src/config/env.ts b/apps/bot/src/config/env.ts index 62a53d6..7f1bb32 100644 --- a/apps/bot/src/config/env.ts +++ b/apps/bot/src/config/env.ts @@ -1,9 +1,22 @@ -/* eslint-disable unicorn/prevent-abbreviations */ import { z } from 'zod'; export const envSchema = z.object({ BOT_TOKEN: z.string(), BOT_URL: z.string(), + RATE_LIMIT: z + .string() + .transform((value) => Number.parseInt(value, 10)) + .default('2'), + RATE_LIMIT_TIME: z + .string() + .transform((value) => Number.parseInt(value, 10)) + .default('3000'), + REDIS_HOST: z.string().default('redis'), + REDIS_PASSWORD: z.string(), + REDIS_PORT: z + .string() + .transform((value) => Number.parseInt(value, 10)) + .default('6379'), }); export const env = envSchema.parse(process.env); diff --git a/apps/bot/src/config/keyboards.ts b/apps/bot/src/config/keyboards.ts new file mode 100644 index 0000000..bbde0a1 --- /dev/null +++ b/apps/bot/src/config/keyboards.ts @@ -0,0 +1,38 @@ +import { + type InlineKeyboardMarkup, + type ReplyKeyboardMarkup, + type ReplyKeyboardRemove, +} from '@grammyjs/types'; + +export const KEYBOARD_SHARE_PHONE = { + reply_markup: { + keyboard: [ + [ + { + request_contact: true, + text: ' Отправить номер телефона', + }, + ], + ], + one_time_keyboard: true, + } as ReplyKeyboardMarkup, +}; + +export const KEYBOARD_REMOVE = { + reply_markup: { + remove_keyboard: true, + } as ReplyKeyboardRemove, +}; + +export const KEYBOARD_SHARE_BOT = { + reply_markup: { + inline_keyboard: [ + [ + { + text: ' Воспользоваться ботом', + url: process.env.BOT_URL as string, + }, + ], + ], + } as InlineKeyboardMarkup, +}; diff --git a/apps/bot/src/config/redis.ts b/apps/bot/src/config/redis.ts new file mode 100644 index 0000000..844d847 --- /dev/null +++ b/apps/bot/src/config/redis.ts @@ -0,0 +1 @@ +export const TTL_SESSION = 5 * 60; // 5 minutes in seconds diff --git a/apps/bot/src/index.ts b/apps/bot/src/index.ts index 65c8079..2bf1f47 100644 --- a/apps/bot/src/index.ts +++ b/apps/bot/src/index.ts @@ -1,276 +1,46 @@ -/* eslint-disable canonical/id-match */ -/* eslint-disable consistent-return */ +import { createBot } from './bot'; import { env as environment } from './config/env'; -import { - commandsList, - KEYBOARD_REMOVE, - KEYBOARD_SHARE_BOT, - KEYBOARD_SHARE_PHONE, - MESSAGE_CANCEL, - MESSAGE_INVALID_PHONE, - MESSAGE_NOT_MASTER, - MESSAGE_SHARE_BOT, - MSG_ALREADY_MASTER, - MSG_BECOME_MASTER, - MSG_CONTACT_ADDED, - MSG_CONTACT_FORWARD, - MSG_ERROR, - MSG_NEED_PHONE, - MSG_PHONE_SAVED, - MSG_SEND_CLIENT_CONTACT, - MSG_WELCOME, - MSG_WELCOME_BACK, -} from './message'; -import { isCustomerMaster } from './utils/customer'; -import { isValidPhoneNumber, normalizePhoneNumber } from './utils/phone'; -import { CustomersService } from '@repo/graphql/api/customers'; -import { RegistrationService } from '@repo/graphql/api/registration'; -import { Enum_Customer_Role } from '@repo/graphql/types'; -import { Scenes, session, Telegraf, type Context as TelegrafContext } from 'telegraf'; -import { message } from 'telegraf/filters'; -import { - type SceneContextScene, - type SceneSession, - type WizardContextWizard, - type WizardSessionData, -} from 'telegraf/typings/scenes'; +import { logger } from './utils/logger'; +import { getRedisInstance } from './utils/redis'; +import { run } from '@grammyjs/runner'; -// Расширяем контекст бота для работы с сценами и сессиями -type BotContext = TelegrafContext & { - scene: SceneContextScene; - session: SceneSession; - wizard: WizardContextWizard; -}; - -// Создаём экземпляр бота с токеном -const bot = new Telegraf(environment.BOT_TOKEN); - -// Создаём менеджер сцен и подключаем сессию -const stage = new Scenes.Stage(); -bot.use(session({ defaultSession: () => ({ __scenes: { cursor: 0, state: {} } }) })); -bot.use(stage.middleware()); - -// Сцена добавления контакта клиента мастером -const addContactScene = new Scenes.WizardScene( - 'add-contact', - - // Шаг 1: Просим отправить контакт клиента - async (context) => { - await context.reply(MSG_SEND_CLIENT_CONTACT, { parse_mode: 'HTML' }); - return context.wizard.next(); - }, - - // Шаг 2: Обрабатываем полученный контакт - async (context) => { - if (!context.from) { - await context.reply('Ошибка: не удалось определить пользователя'); - return context.scene.leave(); - } - - // Команда отмены — выход из сцены - if (context.message && 'text' in context.message && context.message.text === '/cancel') { - await context.reply(MESSAGE_CANCEL + commandsList, { parse_mode: 'HTML' }); - return context.scene.leave(); - } - - // Проверяем, что отправлен контакт (через кнопку Telegram) - if (!context.message || !('contact' in context.message)) { - await context.reply('Пожалуйста, отправьте контакт клиента через кнопку Telegram'); - return; // остаёмся в сцене, ждем корректный контакт - } - - const telegramId = context.from.id; - const customerService = new CustomersService({ telegramId }); - - // Проверяем, что текущий пользователь — мастер - const { customer } = await customerService.getCustomer({ telegramId }); - if (!customer || !isCustomerMaster(customer)) { - await context.reply(MESSAGE_NOT_MASTER, { parse_mode: 'HTML' }); - return context.scene.leave(); - } - - const { contact } = context.message; - const name = `${contact.first_name || ''} ${contact.last_name || ''}`.trim(); - const phone = normalizePhoneNumber(contact.phone_number); - - // Проверяем валидность номера телефона - if (!isValidPhoneNumber(phone)) { - await context.reply(MESSAGE_INVALID_PHONE, { parse_mode: 'HTML' }); - return; // остаёмся в сцене, ждем правильный номер - } - - try { - // Проверяем, есть ли клиент с таким номером - const { customer: existingCustomer } = await customerService.getCustomer({ phone }); - let documentId = existingCustomer?.documentId; - - // Если клиента нет, создаём нового - if (!documentId) { - const registrationService = new RegistrationService(); - const createCustomerResult = await registrationService.createCustomer({ name, phone }); - - documentId = createCustomerResult?.createCustomer?.documentId; - if (!documentId) throw new Error('Клиент не создан'); - } - - // Добавляем текущего мастера к клиенту - const masters = [customer.documentId]; - await customerService.addMasters({ data: { masters }, documentId }); - - // Отправляем подтверждения и инструкции - await context.reply(MSG_CONTACT_ADDED(name), { parse_mode: 'HTML' }); - await context.reply(MSG_CONTACT_FORWARD, { parse_mode: 'HTML' }); - await context.reply(MESSAGE_SHARE_BOT, { ...KEYBOARD_SHARE_BOT, parse_mode: 'HTML' }); - } catch (error) { - await context.reply(MSG_ERROR(error), { parse_mode: 'HTML' }); - } finally { - await context.reply(commandsList, { ...KEYBOARD_REMOVE, parse_mode: 'HTML' }); - context.scene.leave(); - } - }, -); - -// Регистрируем сцену -stage.register(addContactScene); - -// Команда /start — приветствие и запрос номера, если пользователь новый -bot.start(async (context) => { - const telegramId = context.from.id; - - const customerService = new CustomersService({ telegramId }); - const { customer } = await customerService.getCustomer({ telegramId }); - - if (customer) { - // Пользователь уже зарегистрирован — приветствуем - return context.reply(MSG_WELCOME_BACK(customer.name) + commandsList, { - ...KEYBOARD_REMOVE, - parse_mode: 'HTML', - }); - } - - // Новый пользователь — просим поделиться номером - return context.reply(MSG_WELCOME, { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }); +const bot = createBot({ + token: environment.BOT_TOKEN, }); -// Команда /help — список команд -bot.command('help', async (context) => { - return context.reply(commandsList, { ...KEYBOARD_REMOVE, parse_mode: 'HTML' }); +bot.catch((error) => { + logger.error('Grammy bot error:'); + logger.error(`Message: ${error?.message}`); + logger.error(error.error); }); -// Команда /addcontact — начать сцену добавления контакта -bot.command('addcontact', async (context) => { - const telegramId = context.from.id; - const customerService = new CustomersService({ telegramId }); - const { customer } = await customerService.getCustomer({ telegramId }); +const runner = run(bot); +const redis = getRedisInstance(); - if (!customer) { - // Нет номера — просим поделиться - return context.reply(MSG_NEED_PHONE, { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }); - } - - if (!isCustomerMaster(customer)) { - // Нет прав мастера - return context.reply(MESSAGE_NOT_MASTER, { parse_mode: 'HTML' }); - } - - // Входим в сцену - return context.scene.enter('add-contact'); -}); - -// Команда /becomemaster — запрос статуса мастера -bot.command('becomemaster', async (context) => { - const telegramId = context.from.id; - const customerService = new CustomersService({ telegramId }); - const { customer } = await customerService.getCustomer({ telegramId }); - - if (!customer) { - return context.reply(MSG_NEED_PHONE, { ...KEYBOARD_SHARE_PHONE, parse_mode: 'HTML' }); - } - - if (isCustomerMaster(customer)) { - return context.reply(MSG_ALREADY_MASTER, { parse_mode: 'HTML' }); - } - - // Обновляем роль клиента на мастер - const response = await customerService - .updateCustomer({ - data: { role: Enum_Customer_Role.Master }, - }) - .catch((error) => { - context.reply(MSG_ERROR(error), { parse_mode: 'HTML' }); - }); - - if (response) { - return context.reply(MSG_BECOME_MASTER, { parse_mode: 'HTML' }); - } -}); - -// Команда /sharebot — прислать ссылку на бота -bot.command('sharebot', async (context) => { - await context.reply(MSG_CONTACT_FORWARD, { parse_mode: 'HTML' }); - await context.reply(MESSAGE_SHARE_BOT, { ...KEYBOARD_SHARE_BOT, parse_mode: 'HTML' }); -}); - -// Обработка получения контакта от пользователя (регистрация или обновление) -bot.on(message('contact'), async (context) => { - const telegramId = context.from.id; - const { contact } = context.message; - const name = `${contact.first_name || ''} ${contact.last_name || ''}`.trim(); - - // Проверка наличия номера телефона - if (!contact.phone_number) { - return context.reply(MESSAGE_INVALID_PHONE, { parse_mode: 'HTML' }); - } - - // Нормализация и валидация номера - const phone = normalizePhoneNumber(contact.phone_number); - if (!isValidPhoneNumber(phone)) { - return context.reply(MESSAGE_INVALID_PHONE, { parse_mode: 'HTML' }); - } - - const registrationService = new RegistrationService(); +async function gracefulShutdown(signal: string) { + logger.info(`Received ${signal}, starting graceful shutdown...`); try { - const { customer } = await registrationService.getCustomer({ phone }); + await runner.stop(); + logger.info('Bot stopped'); - if (customer && !customer.telegramId) { - // Пользователь добавлен ранее мастером — обновляем данные - await registrationService.updateCustomer({ - data: { active: true, name, telegramId }, - documentId: customer.documentId, - }); - - return context.reply(MSG_PHONE_SAVED + commandsList, { - ...KEYBOARD_REMOVE, - parse_mode: 'HTML', - }); - } - - // Новый пользователь — создаём и активируем - const response = await registrationService.createCustomer({ name, phone, telegramId }); - - const documentId = response?.createCustomer?.documentId; - if (!documentId) { - throw new Error('Не удалось создать клиента: отсутствует documentId'); - } - - await registrationService.updateCustomer({ - data: { active: true }, - documentId, - }); - - return context.reply(MSG_PHONE_SAVED + commandsList, { - ...KEYBOARD_REMOVE, - parse_mode: 'HTML', - }); + redis.disconnect(); + logger.info('Redis disconnected'); } catch (error) { - return context.reply(MSG_ERROR(error), { parse_mode: 'HTML' }); + const err_ = error as Error; + logger.error('Error during graceful shutdown:' + err_.message || ''); } +} + +process.once('SIGINT', () => gracefulShutdown('SIGINT')); +process.once('SIGTERM', () => gracefulShutdown('SIGTERM')); + +process.on('unhandledRejection', (reason) => { + logger.error('Unhandled Rejection: ' + reason); }); -// Запуск бота -bot.launch(); +process.on('uncaughtException', (error) => { + logger.error('Uncaught Exception: ' + error); +}); -// Корректное завершение работы -process.once('SIGINT', () => bot.stop('SIGINT')); -process.once('SIGTERM', () => bot.stop('SIGTERM')); +logger.info('Bot started'); diff --git a/apps/bot/src/message.ts b/apps/bot/src/message.ts deleted file mode 100644 index 8f7dedc..0000000 --- a/apps/bot/src/message.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { env as environment } from './config/env'; -import { type ReplyKeyboardRemove } from 'telegraf/types'; - -export const commandsList = ` -\n📋 Доступные команды: -• /addcontact — добавить контакт клиента -• /becomemaster — стать мастером -• /sharebot — поделиться ботом -• /help — список команд -\n -Откройте приложение кнопкой "Открыть", чтобы отредактировать свой профиль или создать запись -`; - -export const KEYBOARD_SHARE_PHONE = { - reply_markup: { - keyboard: [ - [ - { - request_contact: true, - text: '📱 Отправить номер телефона', - }, - ], - ], - one_time_keyboard: true, - }, -}; - -export const KEYBOARD_REMOVE = { - reply_markup: { - remove_keyboard: true, - } as ReplyKeyboardRemove, -}; - -export const KEYBOARD_SHARE_BOT = { - reply_markup: { - inline_keyboard: [ - [ - { - text: '🤖Воспользоваться ботом', - url: environment.BOT_URL, - }, - ], - ], - }, -}; - -export const MESSAGE_NOT_MASTER = - '⛔️ Только мастер может добавлять контакты\nСтать мастером можно на странице профиля в приложении или с помощью команды /becomemaster'; - -export const MSG_WELCOME = - '👋 Добро пожаловать!\nПожалуйста, поделитесь своим номером телефона для регистрации'; - -export const MSG_WELCOME_BACK = (name: string) => - `👋 С возвращением, ${name}!`; - -export const MSG_NEED_PHONE = - '📱 Чтобы добавить контакт, сначала поделитесь своим номером телефона'; - -export const MSG_SEND_CLIENT_CONTACT = - '👤 Отправьте контакт клиента, которого вы хотите добавить. \nДля отмены операции используйте команду /cancel'; - -export const MSG_ALREADY_MASTER = '🎉 Вы уже являетесь мастером!'; - -export const MSG_BECOME_MASTER = '🥳 Поздравляем! Теперь вы мастер'; - -export const MSG_ERROR = (error?: unknown) => - `❌ Произошла ошибка\n${error ? String(error) : ''}`; - -export const MSG_PHONE_SAVED = - '✅ Спасибо! Мы сохранили ваш номер телефона\nТеперь вы можете открыть приложение или воспользоваться командами бота'; - -export const MSG_CONTACT_ADDED = (name: string) => - `✅ Добавили ${name} в список ваших клиентов\n\nПригласите клиента в приложение, чтобы вы могли добавлять с ним записи`; - -export const MSG_CONTACT_FORWARD = - 'Перешлите пользователю следующее сообщение, чтобы он мог начать пользоваться ботом ⬇️'; - -export const MESSAGE_SHARE_BOT = - '📅 Воспользуйтесь этим ботом для записи к вашему мастеру!\nНажмите кнопку ниже, чтобы начать'; - -export const MESSAGE_CANCEL = '❌ Отменена операции'; - -export const MESSAGE_INVALID_PHONE = '❌ Некорректный номер телефона'; diff --git a/apps/bot/src/utils/logger.ts b/apps/bot/src/utils/logger.ts new file mode 100644 index 0000000..c440158 --- /dev/null +++ b/apps/bot/src/utils/logger.ts @@ -0,0 +1,13 @@ +/* eslint-disable turbo/no-undeclared-env-vars */ +import pino from 'pino'; + +export const logger = pino({ + transport: { + level: process.env.NODE_ENV === 'production' ? 'info' : 'debug', + options: { + colorize: true, + translateTime: true, + }, + target: 'pino-pretty', + }, +}); diff --git a/apps/bot/src/utils/messages.ts b/apps/bot/src/utils/messages.ts new file mode 100644 index 0000000..35f578d --- /dev/null +++ b/apps/bot/src/utils/messages.ts @@ -0,0 +1,3 @@ +export function combine(...messages: string[]) { + return messages.join('\n\n'); +} diff --git a/apps/bot/src/utils/redis.ts b/apps/bot/src/utils/redis.ts new file mode 100644 index 0000000..499b08d --- /dev/null +++ b/apps/bot/src/utils/redis.ts @@ -0,0 +1,23 @@ +import { env } from '@/config/env'; +import { logger } from '@/utils/logger'; +import Redis from 'ioredis'; + +const instance: Redis = createRedisInstance(); + +export function getRedisInstance() { + if (!instance) return createRedisInstance(); + + return instance; +} + +function createRedisInstance() { + const redis = new Redis({ + host: env.REDIS_HOST, + password: env.REDIS_PASSWORD, + port: env.REDIS_PORT, + }); + + redis.on('error', logger.error); + + return redis; +} diff --git a/apps/bot/src/utils/session.ts b/apps/bot/src/utils/session.ts new file mode 100644 index 0000000..6ac5fb4 --- /dev/null +++ b/apps/bot/src/utils/session.ts @@ -0,0 +1,5 @@ +import { type Context } from '@/bot/context'; + +export function getSessionKey(ctx: Omit) { + return ctx.chat?.id.toString(); +} diff --git a/apps/bot/src/utils/urls.ts b/apps/bot/src/utils/urls.ts new file mode 100644 index 0000000..f96e42a --- /dev/null +++ b/apps/bot/src/utils/urls.ts @@ -0,0 +1,5 @@ +import { TIKTOK_URL_REGEX } from '@/constants/regex'; + +export function validateTikTokUrl(url: string) { + return TIKTOK_URL_REGEX.test(url); +} diff --git a/apps/bot/tsconfig.json b/apps/bot/tsconfig.json index 38cb443..b151a7f 100644 --- a/apps/bot/tsconfig.json +++ b/apps/bot/tsconfig.json @@ -8,7 +8,7 @@ "moduleResolution": "Node", "module": "CommonJS", "paths": { - "@/*": ["./*"] + "@/*": ["./src/*"] } }, "include": ["."], diff --git a/apps/web/BAN_CHECK_README.md b/apps/web/BAN_CHECK_README.md new file mode 100644 index 0000000..f2318ab --- /dev/null +++ b/apps/web/BAN_CHECK_README.md @@ -0,0 +1,240 @@ +# Система проверки бана пользователей + +## Обзор + +Реализована многоуровневая система проверки бана пользователей, которая предотвращает доступ заблокированных пользователей к функциональности приложения. + +## 1. База данных (`bannedUntil` поле) + +В Strapi добавлено поле `bannedUntil` типа `datetime` в модель `Customer`: +- `null` = пользователь не забанен +- `дата в будущем` = временный бан до указанной даты +- `дата в далеком будущем` = постоянный бан + +## 2. Утилита проверки (`packages/utils/src/customer.ts`) + +```typescript +export function isCustomerBanned(customer: { bannedUntil?: string | null }): boolean { + return Boolean(customer.bannedUntil && new Date() < new Date(customer.bannedUntil)); +} +``` + +## 3. Next Auth проверка (`apps/web/config/auth.ts`) + +В `authorize` callback добавлена проверка бана: + +```typescript +async authorize(credentials) { + const { telegramId } = credentials ?? {}; + if (!telegramId) { throw new Error('Invalid Telegram ID'); } + + try { + const { query } = await getClientWithToken(); + const result = await query({ + query: GetCustomerDocument, + variables: { telegramId: Number(telegramId) }, + }); + const customer = result.data.customers.at(0); + + if (!customer || isCustomerBanned(customer)) { + throw new Error('User is banned or not found'); + } + return { id: telegramId }; + } catch (error) { + throw new Error('Authentication failed'); + } +} +``` + +## 4. Универсальная проверка в BaseService (`packages/graphql/api/base.ts`) + +Добавлен метод `checkIsBanned()` в `BaseService`: + +```typescript +/** + * Универсальная проверка статуса бана пользователя + * Должна вызываться в начале каждого метода сервиса + */ +protected async checkIsBanned() { + const { query } = await getClientWithToken(); + const result = await query({ + query: GQL.GetCustomerDocument, + variables: this._user, + }); + const customer = result.data.customers.at(0); + + if (!customer) { + throw new Error(BASE_ERRORS.NOT_FOUND_CUSTOMER); + } + + if (isCustomerBanned(customer)) { + throw new Error(ERRORS.NO_PERMISSION); + } + + return { customer }; +} +``` + +**Использование в сервисах:** +```typescript +async someMethod() { + await this.checkIsBanned(); // Проверка бана в начале метода + // ... остальная логика +} +``` + +**Обновленные сервисы:** +- ✅ `CustomersService` - все методы +- ✅ `ServicesService` - все методы +- ✅ `OrdersService` - все методы +- ✅ `SlotsService` - все методы +- ✅ `RegistrationService` - добавлена собственная проверка + +**Преимущества:** +- Автоматическая проверка во всех сервисах, наследующих от BaseService +- Единая точка проверки бана +- Работает как в веб-приложении, так и в боте +- Простота добавления в новые методы +- Защита всех API методов от забаненных пользователей + +## 5. Защита от изменения статуса бана (`packages/graphql/api/customers.ts` и `registration.ts`) + +Пользователи не могут изменять поле `bannedUntil` самостоятельно: + +```typescript +// В CustomersService +async updateCustomer(variables: Omit, 'documentId'>) { + await this.checkBanStatus(); + + const { customer } = await this._getUser(); + + // Проверяем, что пользователь не пытается изменить поле bannedUntil + if (variables.data.bannedUntil !== undefined) { + throw new Error(ERRORS.NO_PERMISSION); + } + + // ... остальная логика обновления +} + +// В RegistrationService +async updateCustomer(variables: VariablesOf) { + // Проверяем бан для существующего пользователя + if (variables.documentId) { + const { query } = await getClientWithToken(); + const result = await query({ + query: GQL.GetCustomerDocument, + variables: { documentId: variables.documentId }, + }); + const customer = result.data.customers.at(0); + if (customer && isCustomerBanned(customer)) { + throw new Error(ERRORS.NO_PERMISSION); + } + } + + if (variables.data.bannedUntil) { + throw new Error(ERRORS.NO_PERMISSION); + } + + // ... остальная логика обновления +} +``` + +**Преимущества:** +- Пользователи не могут снять с себя бан +- Только администраторы могут изменять статус блокировки +- Дополнительный уровень безопасности +- Защита работает во всех сервисах, которые обновляют данные пользователей +- Единая ошибка `NO_PERMISSION` для всех случаев отсутствия доступа + +## 6. Client-side Check (`components/auth/ban-check.tsx`) + +React компонент для проверки бана на клиенте: + +```typescript +export function BanCheck({ children }: Readonly) { + const { data: session } = useSession(); + const router = useRouter(); + const isBanned = useIsBanned(); + + useEffect(() => { + if (session?.user?.telegramId && isBanned) { + router.push('/banned'); + } + }, [session?.user?.telegramId, isBanned, router]); + + if (session?.user?.telegramId && isBanned) { + return null; + } + + return <>{children}; +} +``` + +**Использование в layout:** +```typescript +export default function Layout({ children }: Readonly) { + return ( + + + +
{children}
+ +
+
+ ); +} +``` + +## 7. Hook для проверки бана (`hooks/api/customers.ts`) + +```typescript +export const useIsBanned = () => { + const { data: { customer } = {} } = useCustomerQuery(); + if (!customer) return false; + return isCustomerBanned(customer); +}; +``` + +## 8. Страница для забаненных пользователей (`apps/web/app/(auth)/banned/page.tsx`) + +Создана специальная страница с информацией о бане и возможностью выхода из аккаунта. + +## 9. Централизованные ошибки (`packages/graphql/constants/errors.ts`) + +```typescript +export const ERRORS = { + NO_PERMISSION: 'Нет доступа', +} as const; +``` + +## Архитектура системы + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ Next Auth │ │ BaseService │ │ Client-side │ +│ (авторизация) │ │ (API методы) │ │ (UI) │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ │ + ▼ ▼ ▼ +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ isCustomerBanned│ │ checkBanStatus()│ │ BanCheck │ +│ (утилита) │ │ (метод) │ │ (компонент) │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ │ + └───────────────────────┼───────────────────────┘ + ▼ + ┌─────────────────────────┐ + │ bannedUntil (DB) │ + │ (Strapi/PostgreSQL) │ + └─────────────────────────┘ +``` + +## Преимущества системы + +✅ **Многоуровневая защита** - проверка на всех уровнях приложения +✅ **Универсальность** - работает в веб-приложении и боте +✅ **Простота использования** - один вызов `checkBanStatus()` в начале метода +✅ **Безопасность** - пользователи не могут обойти бан +✅ **UX** - понятные сообщения и страница для забаненных +✅ **DRY принцип** - нет дублирования кода +✅ **Легкость расширения** - просто добавить новые проверки \ No newline at end of file diff --git a/apps/web/app/(auth)/banned/page.tsx b/apps/web/app/(auth)/banned/page.tsx new file mode 100644 index 0000000..26dd9f2 --- /dev/null +++ b/apps/web/app/(auth)/banned/page.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { Container } from '@/components/layout'; +import { Button } from '@repo/ui/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@repo/ui/components/ui/card'; +import { AlertTriangle, Ban } from 'lucide-react'; +import { signOut } from 'next-auth/react'; + +const handleSignOut = () => { + signOut({ callbackUrl: '/' }); +}; + +export default function BannedPage() { + return ( + +
+ + +
+ +
+ Аккаунт заблокирован + + Ваш аккаунт был заблокирован администратором. Для получения дополнительной информации + обратитесь в поддержку. + +
+ +
+
+ +
+

Возможные причины блокировки:

+
    +
  • Нарушение правил использования сервиса
  • +
  • Спам или нежелательная активность
  • +
  • Множественные жалобы от других пользователей
  • +
  • Технические проблемы с аккаунтом
  • +
+
+
+
+ +
+
+
+
+ ); +} diff --git a/apps/web/app/(main)/layout.tsx b/apps/web/app/(main)/layout.tsx index 700358a..3ec8cac 100644 --- a/apps/web/app/(main)/layout.tsx +++ b/apps/web/app/(main)/layout.tsx @@ -1,6 +1,6 @@ 'use client'; -import { UpdateProfile } from '@/components/auth'; +import { CheckBanned, UpdateProfile } from '@/components/auth'; import { BottomNav } from '@/components/navigation'; import { EmptyProvider } from '@/providers/empty'; import { TelegramProvider } from '@/providers/telegram'; @@ -13,10 +13,12 @@ export default function Layout({ children }: Readonly) { const Provider = isTG ? TelegramProvider : EmptyProvider; return ( - - -
{children}
- -
+ + + +
{children}
+ +
+
); } diff --git a/apps/web/app/(main)/orders/page.tsx b/apps/web/app/(main)/orders/page.tsx index a47d2fa..e482ec9 100644 --- a/apps/web/app/(main)/orders/page.tsx +++ b/apps/web/app/(main)/orders/page.tsx @@ -1,6 +1,6 @@ 'use client'; import { Container } from '@/components/layout'; -import { ClientsOrdersList, OrdersList } from '@/components/orders'; +import { OrdersList } from '@/components/orders'; import { DateSelect } from '@/components/orders/orders-list/date-select'; import { DateTimeStoreProvider } from '@/stores/datetime'; @@ -10,7 +10,6 @@ export default function ProfilePage() {
- diff --git a/apps/web/components/auth/check-banned.tsx b/apps/web/components/auth/check-banned.tsx new file mode 100644 index 0000000..254d8e4 --- /dev/null +++ b/apps/web/components/auth/check-banned.tsx @@ -0,0 +1,20 @@ +/* eslint-disable sonarjs/function-return-type */ +'use client'; + +import { useIsBanned } from '@/hooks/api/customers'; +import { redirect, RedirectType } from 'next/navigation'; +import { type PropsWithChildren, useEffect } from 'react'; + +export function CheckBanned({ children }: Readonly) { + const isBanned = useIsBanned(); + + useEffect(() => { + if (isBanned) { + redirect('/banned', RedirectType.replace); + } + }, [isBanned]); + + if (isBanned) return null; + + return children; +} diff --git a/apps/web/components/auth/index.ts b/apps/web/components/auth/index.ts index 69a7357..6309547 100644 --- a/apps/web/components/auth/index.ts +++ b/apps/web/components/auth/index.ts @@ -1 +1,2 @@ +export * from './check-banned'; export * from './update-profile'; diff --git a/apps/web/components/orders/order-form/index.tsx b/apps/web/components/orders/order-form/index.tsx index 68ed8b3..92f1bca 100644 --- a/apps/web/components/orders/order-form/index.tsx +++ b/apps/web/components/orders/order-form/index.tsx @@ -27,13 +27,17 @@ function getStepComponent(step: string) { return STEP_COMPONENTS[step] ?? null; } -const BUTTON_COMPONENTS: Record = { - '': , +const BUTTON_COMPONENTS: Record = { + 'client-select': , 'datetime-select': , + error: null, + 'master-select': , + 'service-select': , + success: null, }; function getButtonComponent(step: string) { - return BUTTON_COMPONENTS[step] ?? ; + return BUTTON_COMPONENTS[step]; } export const OrderForm = withContext(OrderStoreProvider)(function () { diff --git a/apps/web/components/orders/orders-list/index.tsx b/apps/web/components/orders/orders-list/index.tsx index 6457199..3c98819 100644 --- a/apps/web/components/orders/orders-list/index.tsx +++ b/apps/web/components/orders/orders-list/index.tsx @@ -1,66 +1,16 @@ 'use client'; -import { OrderCard } from '@/components/shared/order-card'; +import { OrdersList as OrdersListComponent } from './orders-list'; +import { useCurrentAndNext } from './utils'; import { useCustomerQuery, useIsMaster } from '@/hooks/api/customers'; import { useOrdersInfiniteQuery } from '@/hooks/api/orders'; import { useDateTimeStore } from '@/stores/datetime'; -import { Button } from '@repo/ui/components/ui/button'; +import type * as GQL from '@repo/graphql/types'; import { getDateUTCRange } from '@repo/utils/datetime-format'; -export function ClientsOrdersList() { - const { data: { customer } = {} } = useCustomerQuery(); - - const isMaster = useIsMaster(); - - const selectedDate = useDateTimeStore((store) => store.date); - const { endOfDay, startOfDay } = getDateUTCRange(selectedDate).day(); - - const { - data: { pages } = {}, - fetchNextPage, - hasNextPage, - isLoading, - } = useOrdersInfiniteQuery( - { - filters: { - slot: { - datetime_start: selectedDate - ? { - gte: startOfDay, - lt: endOfDay, - } - : undefined, - master: { - documentId: { - eq: isMaster ? customer?.documentId : undefined, - }, - }, - }, - }, - }, - { enabled: Boolean(customer?.documentId) && isMaster }, - ); - - const orders = pages?.flatMap((page) => page.orders) ?? []; - - if (!orders?.length || isLoading || !isMaster) return null; - - return ( -
-

Записи клиентов

- {orders?.map((order) => order && )} - {hasNextPage && ( - - )} -
- ); -} - export function OrdersList() { const { data: { customer } = {} } = useCustomerQuery(); - + const isMaster = useIsMaster(); const selectedDate = useDateTimeStore((store) => store.date); const { endOfDay, startOfDay } = getDateUTCRange(selectedDate).day(); @@ -72,40 +22,32 @@ export function OrdersList() { } = useOrdersInfiniteQuery( { filters: { - client: { - documentId: { - eq: customer?.documentId, - }, - }, + client: isMaster ? undefined : { documentId: { eq: customer?.documentId } }, slot: { - datetime_start: selectedDate - ? { - gte: startOfDay, - lt: endOfDay, - } - : undefined, + datetime_start: selectedDate ? { gte: startOfDay, lt: endOfDay } : undefined, + master: isMaster ? { documentId: { eq: customer?.documentId } } : undefined, }, }, }, { enabled: Boolean(customer?.documentId) }, ); - const orders = pages?.flatMap((page) => page.orders) ?? []; + const orders = + (pages?.flatMap((page) => page.orders).filter(Boolean) as GQL.OrderFieldsFragment[]) ?? []; + + const { current, next } = useCurrentAndNext(orders); if (!orders?.length || isLoading) return null; return ( -
-

Ваши записи

- {orders?.map( - (order) => - order && , - )} - {hasNextPage && ( - - )} -
+ fetchNextPage()} + orders={orders} + title={isMaster ? 'Записи клиентов' : 'Ваши записи'} + /> ); } diff --git a/apps/web/components/orders/orders-list/orders-list.tsx b/apps/web/components/orders/orders-list/orders-list.tsx new file mode 100644 index 0000000..d7b3e55 --- /dev/null +++ b/apps/web/components/orders/orders-list/orders-list.tsx @@ -0,0 +1,78 @@ +import { getOrderStatus, getStatusText, type OrderStatus } from './utils'; +import { OrderCard } from '@/components/shared/order-card'; +import type * as GQL from '@repo/graphql/types'; +import { Button } from '@repo/ui/components/ui/button'; +import { cn } from '@repo/ui/lib/utils'; + +type Order = GQL.OrderFieldsFragment; + +type OrdersListProps = Pick[0], 'avatarSource'> & { + readonly current: null | Order; + readonly hasNextPage?: boolean; + readonly next: null | Order; + readonly onLoadMore?: () => void; + readonly orders: Order[]; + readonly title: string; +}; + +export function OrdersList({ + avatarSource, + current, + hasNextPage = false, + next, + onLoadMore, + orders, + title, +}: OrdersListProps) { + return ( +
+

{title}

+ {orders?.map((order) => { + if (!order) return null; + + const status = getOrderStatus(order, current, next); + + return ( + + + + ); + })} + {hasNextPage && onLoadMore && ( + + )} +
+ ); +} + +function DateStatusWrapper({ + children, + status, +}: { + readonly children: React.ReactNode; + readonly status: OrderStatus; +}) { + if (!status) return <>{children}; + + const statusText = getStatusText(status); + + return ( +
+ {statusText && ( +
+ + {statusText} + +
+ )} + {children} +
+ ); +} diff --git a/apps/web/components/orders/orders-list/utils.ts b/apps/web/components/orders/orders-list/utils.ts new file mode 100644 index 0000000..02bd0cf --- /dev/null +++ b/apps/web/components/orders/orders-list/utils.ts @@ -0,0 +1,65 @@ +import * as GQL from '@repo/graphql/types'; +import dayjs from 'dayjs'; +import { useMemo } from 'react'; + +export type OrderStatus = 'current' | 'next' | undefined; + +type Order = GQL.OrderFieldsFragment; + +export function getCurrentAndNext(orders: Order[]) { + const now = dayjs(); + + let current: null | Order = null; + let next: null | Order = null; + + for (let index = orders.length - 1; index >= 0; index--) { + const order = orders[index]; + const nextOrder = index > 0 ? orders[index - 1] : null; + + if ( + order && + now.isAfter(dayjs(order.datetime_start)) && + now.isBefore(dayjs(order.datetime_end)) + ) { + current = order; + } + + if ( + nextOrder?.state === GQL.Enum_Order_State.Approved && + now.isSame(dayjs(nextOrder?.datetime_start), 'day') + ) { + next = nextOrder; + } + } + + return { current, next }; +} + +export function getOrderStatus( + order: Order, + current: null | Order, + next: null | Order, +): OrderStatus { + if (current && order.documentId === current.documentId) return 'current'; + if (next && order.documentId === next.documentId) return 'next'; + return undefined; +} + +export function getStatusText(status: OrderStatus): string { + switch (status) { + case 'current': + return 'Текущая запись'; + case 'next': + return 'Следующая запись'; + default: + return ''; + } +} + +export function useCurrentAndNext(orders: Order[]) { + const { current, next } = useMemo(() => { + return getCurrentAndNext(orders); + }, [orders, orders.length]); + + return { current, next }; +} diff --git a/apps/web/components/profile/data-card/index.tsx b/apps/web/components/profile/data-card/index.tsx index 147cc9f..6b76717 100644 --- a/apps/web/components/profile/data-card/index.tsx +++ b/apps/web/components/profile/data-card/index.tsx @@ -7,6 +7,7 @@ import { useCustomerMutation, useCustomerQuery } from '@/hooks/api/customers'; import { Button } from '@repo/ui/components/ui/button'; import { Card } from '@repo/ui/components/ui/card'; import Link from 'next/link'; +import { useState } from 'react'; export function ContactDataCard({ telegramId }: Readonly) { const { data: { customer } = {} } = useCustomerQuery({ telegramId }); @@ -31,7 +32,8 @@ export function ContactDataCard({ telegramId }: Readonly) { export function ProfileDataCard() { const { data: { customer } = {} } = useCustomerQuery(); - const { mutate: updateCustomer } = useCustomerMutation(); + const { cancelChanges, hasChanges, isPending, resetTrigger, saveChanges, updateField } = + useProfileEdit(); if (!customer) return null; @@ -41,8 +43,9 @@ export function ProfileDataCard() { updateCustomer({ data: { name: value } })} + onChange={(value) => updateField('name', value)} value={customer?.name ?? ''} /> @@ -50,13 +53,54 @@ export function ProfileDataCard() { checked={customer.role !== 'client'} description="Разрешить другим пользователям записываться к вам" onChange={(checked) => - updateCustomer({ - data: { role: checked ? Role.Master : Role.Client }, - }) + updateField('role', checked ? Role.Master : Role.Client) } text="Быть мастером" /> */} + {hasChanges && ( +
+ + +
+ )}
); } + +function useProfileEdit() { + const { isPending, mutate } = useCustomerMutation(); + const [pendingChanges, setPendingChanges] = useState>({}); + const [resetTrigger, setResetTrigger] = useState(0); + + const updateField = (field: string, value: unknown) => { + setPendingChanges((previous) => ({ ...previous, [field]: value })); + }; + + const saveChanges = () => { + if (Object.keys(pendingChanges).length === 0) return; + + mutate({ data: pendingChanges }); + setPendingChanges({}); + }; + + const cancelChanges = () => { + setPendingChanges({}); + setResetTrigger((previous) => previous + 1); + }; + + const hasChanges = Object.keys(pendingChanges).length > 0; + + return { + cancelChanges, + hasChanges, + isPending, + resetTrigger, + saveChanges, + updateField, + }; +} diff --git a/apps/web/components/profile/services/service-data-card.tsx b/apps/web/components/profile/services/service-data-card.tsx index 0768d94..0f4dcc2 100644 --- a/apps/web/components/profile/services/service-data-card.tsx +++ b/apps/web/components/profile/services/service-data-card.tsx @@ -2,8 +2,10 @@ import { NumberField, TextareaField, TextField, TimeField } from '@/components/shared/data-fields'; import { useServiceMutation, useServiceQuery } from '@/hooks/api/services'; +import { Button } from '@repo/ui/components/ui/button'; import { Card } from '@repo/ui/components/ui/card'; import { convertTimeString } from '@repo/utils/datetime-format'; +import { useState } from 'react'; type Props = { serviceId: string; @@ -11,7 +13,8 @@ type Props = { export function ServiceDataCard({ serviceId }: Readonly) { const { data: { service } = {} } = useServiceQuery({ documentId: serviceId }); - const { mutate } = useServiceMutation({ documentId: serviceId }); + const { cancelChanges, hasChanges, isPending, resetTrigger, saveChanges, updateField } = + useServiceEdit(serviceId); if (!service) return null; @@ -20,37 +23,78 @@ export function ServiceDataCard({ serviceId }: Readonly) {
mutate({ data: { name } })} + onChange={(name) => updateField('name', name)} value={service?.name ?? ''} /> - mutate({ - data: { - duration: convertTimeString(time).db(), - }, - }) - } + onChange={(time) => updateField('duration', convertTimeString(time).db())} value={service?.duration ?? ''} /> mutate({ data: { price } })} + onChange={(price) => updateField('price', price)} value={service?.price ?? null} /> mutate({ data: { description } })} + onChange={(description) => updateField('description', description)} rows={4} value={service?.description ?? ''} /> + {hasChanges && ( +
+ + +
+ )}
); } + +function useServiceEdit(serviceId: string) { + const { isPending, mutate } = useServiceMutation({ documentId: serviceId }); + const [pendingChanges, setPendingChanges] = useState>({}); + const [resetTrigger, setResetTrigger] = useState(0); + + const updateField = (field: string, value: unknown) => { + setPendingChanges((previous) => ({ ...previous, [field]: value })); + }; + + const saveChanges = () => { + if (Object.keys(pendingChanges).length === 0) return; + + mutate({ data: pendingChanges }); + setPendingChanges({}); + }; + + const cancelChanges = () => { + setPendingChanges({}); + setResetTrigger((previous) => previous + 1); + }; + + const hasChanges = Object.keys(pendingChanges).length > 0; + + return { + cancelChanges, + hasChanges, + isPending, + resetTrigger, + saveChanges, + updateField, + }; +} diff --git a/apps/web/components/shared/action-panel.tsx b/apps/web/components/shared/action-panel.tsx index cb5f413..5056a2f 100644 --- a/apps/web/components/shared/action-panel.tsx +++ b/apps/web/components/shared/action-panel.tsx @@ -2,7 +2,7 @@ import { Button } from '@repo/ui/components/ui/button'; import { Card } from '@repo/ui/components/ui/card'; -import { Ban, Check, Lock, RotateCcw, Trash2, Undo, Unlock } from 'lucide-react'; +import { Ban, Check, Lock, RotateCcw, Save, Trash2, Undo, Unlock } from 'lucide-react'; type FloatingActionPanelProps = { readonly isLoading?: boolean; @@ -13,6 +13,7 @@ type FloatingActionPanelProps = { readonly onDelete?: () => void; readonly onRepeat?: () => void; readonly onReturn?: () => void; + readonly onSave?: () => void; readonly onToggle?: () => void; }; @@ -25,10 +26,20 @@ export default function FloatingActionPanel({ onDelete, onRepeat, onReturn, + onSave, onToggle, }: FloatingActionPanelProps) { // Если не переданы обработчики, скрываем панель - if (!onCancel && !onConfirm && !onDelete && !onComplete && !onRepeat && !onToggle && !onReturn) + if ( + !onCancel && + !onConfirm && + !onDelete && + !onComplete && + !onRepeat && + !onToggle && + !onReturn && + !onSave + ) return null; return ( @@ -140,6 +151,19 @@ export default function FloatingActionPanel({ Вернуть )} + + {/* Кнопка сохранить */} + {onSave && ( + + )} ); diff --git a/apps/web/components/shared/data-fields/number-field.tsx b/apps/web/components/shared/data-fields/number-field.tsx index 3abede5..a6a750e 100644 --- a/apps/web/components/shared/data-fields/number-field.tsx +++ b/apps/web/components/shared/data-fields/number-field.tsx @@ -10,7 +10,7 @@ type FieldProps = { readonly id: string; readonly label: string; readonly min?: number; - readonly onChange?: (value: null | number) => Promise | void; + readonly onChange?: (value: null | number) => void; readonly readOnly?: boolean; readonly value: null | number; }; diff --git a/apps/web/components/shared/data-fields/text-field.tsx b/apps/web/components/shared/data-fields/text-field.tsx index 54b8442..d508e37 100644 --- a/apps/web/components/shared/data-fields/text-field.tsx +++ b/apps/web/components/shared/data-fields/text-field.tsx @@ -9,7 +9,7 @@ type FieldProps = { readonly disabled?: boolean; readonly id: string; readonly label: string; - readonly onChange?: (value: string) => Promise | void; + readonly onChange?: (value: string) => void; readonly readOnly?: boolean; readonly value: string; }; diff --git a/apps/web/components/shared/data-fields/textarea-field.tsx b/apps/web/components/shared/data-fields/textarea-field.tsx index 4a566aa..ee27851 100644 --- a/apps/web/components/shared/data-fields/textarea-field.tsx +++ b/apps/web/components/shared/data-fields/textarea-field.tsx @@ -8,7 +8,7 @@ type FieldProps = { readonly disabled?: boolean; readonly id: string; readonly label: string; - readonly onChange?: (value: string) => Promise | void; + readonly onChange?: (value: string) => void; readonly readOnly?: boolean; readonly rows?: number; readonly value: string; diff --git a/apps/web/components/shared/data-fields/time-field.tsx b/apps/web/components/shared/data-fields/time-field.tsx index 523a9ca..5d1a106 100644 --- a/apps/web/components/shared/data-fields/time-field.tsx +++ b/apps/web/components/shared/data-fields/time-field.tsx @@ -9,7 +9,7 @@ type FieldProps = { readonly disabled?: boolean; readonly id: string; readonly label: string; - readonly onChange?: (value: string) => Promise | void; + readonly onChange?: (value: string) => void; readonly readOnly?: boolean; readonly value: string; }; diff --git a/apps/web/hooks/api/customers.ts b/apps/web/hooks/api/customers.ts index afb12ac..6e4f4f3 100644 --- a/apps/web/hooks/api/customers.ts +++ b/apps/web/hooks/api/customers.ts @@ -1,7 +1,7 @@ 'use client'; import { getCustomer, updateCustomer } from '@/actions/api/customers'; -import { isCustomerMaster } from '@repo/utils/customer'; +import { isCustomerBanned, isCustomerMaster } from '@repo/utils/customer'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useSession } from 'next-auth/react'; @@ -24,6 +24,14 @@ export const useIsMaster = () => { return isCustomerMaster(customer); }; +export const useIsBanned = () => { + const { data: { customer } = {} } = useCustomerQuery(); + + if (!customer) return false; + + return isCustomerBanned(customer); +}; + export const useCustomerMutation = () => { const { data: session } = useSession(); const telegramId = session?.user?.telegramId; diff --git a/apps/web/package.json b/apps/web/package.json index 5af8dfd..8fb75c4 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -35,7 +35,7 @@ "next-auth": "^4.24.11", "next-intl": "^3.26.0", "next-themes": "^0.4.4", - "next": "15.3.4", + "next": "^15.5.0", "postcss": "catalog:", "radashi": "catalog:", "react-dom": "catalog:", diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index b759d24..362754a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,6 +1,5 @@ services: web: - container_name: web env_file: - .env build: @@ -10,10 +9,28 @@ services: ports: - 3000:3000 bot: - container_name: bot - env_file: - - .env build: context: . dockerfile: ./apps/bot/Dockerfile + env_file: + - .env + depends_on: + - redis restart: always + + redis: + image: redis:8-alpine + restart: always + env_file: + - .env + command: ['redis-server', '--requirepass', '${REDIS_PASSWORD}'] + ports: + - '127.0.0.1:6379:6379' + volumes: + - redis-data:/data + healthcheck: + test: ['CMD', 'redis-cli', 'ping'] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s diff --git a/docker-compose.yml b/docker-compose.yml index d46d2b7..827dfb7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,11 +15,36 @@ services: bot: image: ${DOCKERHUB_USERNAME}/zapishis-bot:${BOT_IMAGE_TAG} + restart: always env_file: - .env - restart: always + depends_on: + - redis networks: - app + + redis: + image: redis:8-alpine + restart: always + env_file: + - .env + command: ['redis-server', '--requirepass', '${REDIS_PASSWORD}'] + volumes: + - redis-data:/data + deploy: + resources: + limits: + cpus: '0.50' + memory: 512M + reservations: + cpus: '0.25' + memory: 256M + healthcheck: + test: ['CMD', 'redis-cli', 'ping'] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s networks: app: diff --git a/packages/graphql/api/base.ts b/packages/graphql/api/base.ts index e881673..fced362 100644 --- a/packages/graphql/api/base.ts +++ b/packages/graphql/api/base.ts @@ -1,11 +1,13 @@ /* eslint-disable canonical/id-match */ import { getClientWithToken } from '../apollo/client'; +import { ERRORS } from '../constants/errors'; import * as GQL from '../types'; +import { isCustomerBanned } from '@repo/utils/customer'; -export const ERRORS = { +const BASE_ERRORS = { MISSING_TELEGRAM_ID: 'Не указан Telegram ID', NOT_FOUND_CUSTOMER: 'Пользователь не найден', -}; +} as const; type UserProfile = { telegramId: number; @@ -16,7 +18,7 @@ export class BaseService { constructor(user: UserProfile) { if (!user?.telegramId) { - throw new Error(ERRORS.MISSING_TELEGRAM_ID); + throw new Error(BASE_ERRORS.MISSING_TELEGRAM_ID); } this._user = user; @@ -32,7 +34,32 @@ export class BaseService { const customer = result.data.customers.at(0); - if (!customer) throw new Error(ERRORS.NOT_FOUND_CUSTOMER); + if (!customer) throw new Error(BASE_ERRORS.NOT_FOUND_CUSTOMER); + + if (isCustomerBanned(customer)) { + throw new Error(ERRORS.NO_PERMISSION); + } + + return { customer }; + } + + protected async checkIsBanned() { + const { query } = await getClientWithToken(); + + const result = await query({ + query: GQL.GetCustomerDocument, + variables: this._user, + }); + + const customer = result.data.customers.at(0); + + if (!customer) { + throw new Error(BASE_ERRORS.NOT_FOUND_CUSTOMER); + } + + if (isCustomerBanned(customer)) { + throw new Error(ERRORS.NO_PERMISSION); + } return { customer }; } diff --git a/packages/graphql/api/customers.ts b/packages/graphql/api/customers.ts index ab47e94..c8bec94 100644 --- a/packages/graphql/api/customers.ts +++ b/packages/graphql/api/customers.ts @@ -1,12 +1,20 @@ import { getClientWithToken } from '../apollo/client'; +import { ERRORS } from '../constants/errors'; import * as GQL from '../types'; import { BaseService } from './base'; import { type VariablesOf } from '@graphql-typed-document-node/core'; export class CustomersService extends BaseService { async addMasters(variables: VariablesOf) { + await this.checkIsBanned(); + const newMasterIds = variables.data.masters; + // Проверяем, что пользователь не пытается изменить поле bannedUntil + if (variables.data.bannedUntil !== undefined) { + throw new Error(ERRORS.NO_PERMISSION); + } + const { mutate, query } = await getClientWithToken(); const getMastersResult = await query({ query: GQL.GetMastersDocument, @@ -34,6 +42,8 @@ export class CustomersService extends BaseService { } async getClients(variables?: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -47,6 +57,8 @@ export class CustomersService extends BaseService { } async getCustomer(variables: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -60,6 +72,8 @@ export class CustomersService extends BaseService { } async getMasters(variables?: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -75,8 +89,15 @@ export class CustomersService extends BaseService { async updateCustomer( variables: Omit, 'documentId'>, ) { + await this.checkIsBanned(); + const { customer } = await this._getUser(); + // Пров еряем, что пользователь не пытается изменить поле bannedUntil + if (variables.data.bannedUntil !== undefined) { + throw new Error(ERRORS.NO_PERMISSION); + } + const { mutate } = await getClientWithToken(); const mutationResult = await mutate({ diff --git a/packages/graphql/api/orders.ts b/packages/graphql/api/orders.ts index 6a0b796..18d8c01 100644 --- a/packages/graphql/api/orders.ts +++ b/packages/graphql/api/orders.ts @@ -1,6 +1,7 @@ /* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable @typescript-eslint/naming-convention */ import { getClientWithToken } from '../apollo/client'; +import { ERRORS as SHARED_ERRORS } from '../constants/errors'; import * as GQL from '../types'; import { BaseService } from './base'; import { CustomersService } from './customers'; @@ -30,7 +31,6 @@ export const ERRORS = { NO_MASTER_SELF_BOOK: 'Нельзя записать к самому себе', NO_ORDER_IN_PAST: 'Нельзя создать запись на время в прошлом', NO_ORDER_OUT_OF_SLOT: 'Время заказа выходит за пределы слота', - NO_PERMISSION: 'Нет доступа', NOT_FOUND_CLIENT: 'Клиент не найден', NOT_FOUND_MASTER: 'Мастер не найден', NOT_FOUND_ORDER: 'Заказ не найден', @@ -39,7 +39,7 @@ export const ERRORS = { SLOT_CLOSED: 'Слот закрыт', }; -const DEFAULT_ORDERS_SORT = ['slot.datetime_start:desc', 'datetime_start:asc']; +const DEFAULT_ORDERS_SORT = ['slot.datetime_start:desc', 'datetime_start:desc']; export class OrdersService extends BaseService { async createOrder(variables: VariablesOf) { @@ -151,17 +151,17 @@ export class OrdersService extends BaseService { const isOrderClient = order.client?.documentId === customer.documentId; const isOrderMaster = order.slot?.master?.documentId === customer.documentId; - if (!isOrderClient && !isOrderMaster) throw new Error(ERRORS.NO_PERMISSION); + if (!isOrderClient && !isOrderMaster) throw new Error(SHARED_ERRORS.NO_PERMISSION); if (isOrderClient && Object.keys(variables.data).length > 1) - throw new Error(ERRORS.NO_PERMISSION); + throw new Error(SHARED_ERRORS.NO_PERMISSION); if ( isOrderClient && variables.data.state && variables.data.state !== GQL.Enum_Order_State.Cancelling ) { - throw new Error(ERRORS.NO_PERMISSION); + throw new Error(SHARED_ERRORS.NO_PERMISSION); } const { mutate } = await getClientWithToken(); @@ -307,7 +307,7 @@ export class OrdersService extends BaseService { private async checkBeforeUpdate(variables: VariablesOf) { if (variables.data.client || variables.data.services?.length || variables.data.slot) { - throw new Error(ERRORS.NO_PERMISSION); + throw new Error(SHARED_ERRORS.NO_PERMISSION); } const { order: existingOrder } = await this.getOrder({ documentId: variables.documentId }); @@ -368,11 +368,11 @@ export class OrdersService extends BaseService { const isOrderMaster = order.slot?.master?.documentId === customer.documentId; if (!isOrderClient && !isOrderMaster) { - throw new Error(ERRORS.NO_PERMISSION); + throw new Error(SHARED_ERRORS.NO_PERMISSION); } if (isOrderClient && variables?.data && Object.keys(variables.data).length > 1) { - throw new Error(ERRORS.NO_PERMISSION); + throw new Error(SHARED_ERRORS.NO_PERMISSION); } if ( @@ -380,7 +380,7 @@ export class OrdersService extends BaseService { variables?.data?.state && variables.data.state !== GQL.Enum_Order_State.Cancelling ) { - throw new Error(ERRORS.NO_PERMISSION); + throw new Error(SHARED_ERRORS.NO_PERMISSION); } } diff --git a/packages/graphql/api/registration.ts b/packages/graphql/api/registration.ts index cf401d6..d65946c 100644 --- a/packages/graphql/api/registration.ts +++ b/packages/graphql/api/registration.ts @@ -1,6 +1,8 @@ import { getClientWithToken } from '../apollo/client'; +import { ERRORS } from '../constants/errors'; import * as GQL from '../types'; import { type VariablesOf } from '@graphql-typed-document-node/core'; +import { isCustomerBanned } from '@repo/utils/customer'; export class RegistrationService { async createCustomer(variables: VariablesOf) { @@ -18,6 +20,10 @@ export class RegistrationService { } async getCustomer(variables: VariablesOf) { + if (variables.telegramId) { + await this.checkBanStatus(variables.telegramId); + } + const { query } = await getClientWithToken(); const result = await query({ @@ -31,6 +37,23 @@ export class RegistrationService { } async updateCustomer(variables: VariablesOf) { + // Проверяем бан для существующего пользователя + if (variables.documentId) { + const { query } = await getClientWithToken(); + const result = await query({ + query: GQL.GetCustomerDocument, + variables: { documentId: variables.documentId }, + }); + const customer = result.data.customers.at(0); + if (customer && isCustomerBanned(customer)) { + throw new Error(ERRORS.NO_PERMISSION); + } + } + + if (variables.data.bannedUntil) { + throw new Error(ERRORS.NO_PERMISSION); + } + const { mutate } = await getClientWithToken(); const mutationResult = await mutate({ @@ -43,4 +66,21 @@ export class RegistrationService { return mutationResult.data; } + + private async checkBanStatus(telegramId: number) { + const { query } = await getClientWithToken(); + + const result = await query({ + query: GQL.GetCustomerDocument, + variables: { telegramId }, + }); + + const customer = result.data.customers.at(0); + + if (customer && isCustomerBanned(customer)) { + throw new Error(ERRORS.NO_PERMISSION); + } + + return { customer }; + } } diff --git a/packages/graphql/api/services.ts b/packages/graphql/api/services.ts index 63adec9..24b7a3d 100644 --- a/packages/graphql/api/services.ts +++ b/packages/graphql/api/services.ts @@ -1,14 +1,13 @@ import { getClientWithToken } from '../apollo/client'; +import { ERRORS } from '../constants/errors'; import * as GQL from '../types'; import { BaseService } from './base'; import { type VariablesOf } from '@graphql-typed-document-node/core'; -const ERRORS = { - NO_PERMISSION: 'No permission', -}; - export class ServicesService extends BaseService { async createService(variables: VariablesOf) { + await this.checkIsBanned(); + const { customer } = await this._getUser(); const { mutate } = await getClientWithToken(); @@ -31,6 +30,8 @@ export class ServicesService extends BaseService { } async getService(variables: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -42,6 +43,8 @@ export class ServicesService extends BaseService { } async getServices(variables: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -53,6 +56,8 @@ export class ServicesService extends BaseService { } async updateService(variables: VariablesOf) { + await this.checkIsBanned(); + await this.checkPermission(variables); const { mutate } = await getClientWithToken(); diff --git a/packages/graphql/api/slots.ts b/packages/graphql/api/slots.ts index 86b0aa2..d14e17c 100644 --- a/packages/graphql/api/slots.ts +++ b/packages/graphql/api/slots.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { getClientWithToken } from '../apollo/client'; +import { ERRORS as SHARED_ERRORS } from '../constants/errors'; import * as GQL from '../types'; import { BaseService } from './base'; import { ServicesService } from './services'; @@ -14,7 +15,6 @@ export const ERRORS = { MISSING_DATETIME_START: 'Не указана дата начала', MISSING_SERVICES_IDS: 'Не указаны услуги', NO_PAST_SLOT: 'Нельзя создать слот в прошлом', - NO_PERMISSION: 'Нет доступа', NOT_FOUND_MASTER: 'Мастер не найден', NOT_FOUND_SERVICE: 'Сервис не найден', NOT_FOUND_SLOT: 'Слот не найден', @@ -24,6 +24,8 @@ export const ERRORS = { export class SlotsService extends BaseService { async createSlot(variables: VariablesOf) { + await this.checkIsBanned(); + await this.checkBeforeCreate(variables); const { customer } = await this._getUser(); @@ -48,6 +50,8 @@ export class SlotsService extends BaseService { } async deleteSlot(variables: VariablesOf) { + await this.checkIsBanned(); + await this.checkPermission(variables); const { slot } = await this.getSlot({ documentId: variables.documentId }); @@ -73,6 +77,8 @@ export class SlotsService extends BaseService { variables: VariablesOf, context: { services: string[] }, ) { + await this.checkIsBanned(); + if (!variables.filters?.datetime_start) throw new Error(ERRORS.MISSING_DATETIME_START); if (!context?.services?.length) throw new Error(ERRORS.MISSING_SERVICES_IDS); @@ -146,6 +152,8 @@ export class SlotsService extends BaseService { } async getSlot(variables: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -157,6 +165,8 @@ export class SlotsService extends BaseService { } async getSlots(variables: VariablesOf) { + await this.checkIsBanned(); + const { query } = await getClientWithToken(); const result = await query({ @@ -168,6 +178,8 @@ export class SlotsService extends BaseService { } async updateSlot(variables: VariablesOf) { + await this.checkIsBanned(); + await this.checkPermission(variables); await this.checkBeforeUpdateDatetime(variables); @@ -288,6 +300,7 @@ export class SlotsService extends BaseService { if (!slot) throw new Error(ERRORS.NOT_FOUND_SLOT); - if (slot?.master?.documentId !== customer?.documentId) throw new Error(ERRORS.NO_PERMISSION); + if (slot?.master?.documentId !== customer?.documentId) + throw new Error(SHARED_ERRORS.NO_PERMISSION); } } diff --git a/packages/graphql/constants/errors.ts b/packages/graphql/constants/errors.ts new file mode 100644 index 0000000..7227a65 --- /dev/null +++ b/packages/graphql/constants/errors.ts @@ -0,0 +1,3 @@ +export const ERRORS = { + NO_PERMISSION: 'Нет доступа', +} as const; diff --git a/packages/graphql/operations/customers.graphql b/packages/graphql/operations/customers.graphql index 3236735..dbc9646 100644 --- a/packages/graphql/operations/customers.graphql +++ b/packages/graphql/operations/customers.graphql @@ -1,5 +1,6 @@ fragment CustomerFields on Customer { active + bannedUntil documentId name phone diff --git a/packages/graphql/types/operations.generated.ts b/packages/graphql/types/operations.generated.ts index d2b366f..2c16615 100644 --- a/packages/graphql/types/operations.generated.ts +++ b/packages/graphql/types/operations.generated.ts @@ -77,6 +77,7 @@ export type BooleanFilterInput = { export type CustomerFiltersInput = { active?: InputMaybe; and?: InputMaybe>>; + bannedUntil?: InputMaybe; blocks?: InputMaybe; clients?: InputMaybe; createdAt?: InputMaybe; @@ -98,6 +99,7 @@ export type CustomerFiltersInput = { export type CustomerInput = { active?: InputMaybe; + bannedUntil?: InputMaybe; blocks?: InputMaybe>>; clients?: InputMaybe>>; masters?: InputMaybe>>; @@ -624,7 +626,7 @@ export type LoginMutationVariables = Exact<{ export type LoginMutation = { __typename?: 'Mutation', login: { __typename?: 'UsersPermissionsLoginPayload', jwt?: string | null | undefined } }; -export type CustomerFieldsFragment = { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined }; +export type CustomerFieldsFragment = { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined }; export type CreateCustomerMutationVariables = Exact<{ name: Scalars['String']['input']; @@ -642,7 +644,7 @@ export type GetCustomerQueryVariables = Exact<{ }>; -export type GetCustomerQuery = { __typename?: 'Query', customers: Array<{ __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined> }; +export type GetCustomerQuery = { __typename?: 'Query', customers: Array<{ __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined> }; export type GetMastersQueryVariables = Exact<{ phone?: InputMaybe; @@ -651,7 +653,7 @@ export type GetMastersQueryVariables = Exact<{ }>; -export type GetMastersQuery = { __typename?: 'Query', customers: Array<{ __typename?: 'Customer', documentId: string, masters: Array<{ __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined> } | null | undefined> }; +export type GetMastersQuery = { __typename?: 'Query', customers: Array<{ __typename?: 'Customer', documentId: string, masters: Array<{ __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined> } | null | undefined> }; export type GetClientsQueryVariables = Exact<{ phone?: InputMaybe; @@ -659,7 +661,7 @@ export type GetClientsQueryVariables = Exact<{ }>; -export type GetClientsQuery = { __typename?: 'Query', customers: Array<{ __typename?: 'Customer', documentId: string, clients: Array<{ __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined> } | null | undefined> }; +export type GetClientsQuery = { __typename?: 'Query', customers: Array<{ __typename?: 'Customer', documentId: string, clients: Array<{ __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined> } | null | undefined> }; export type UpdateCustomerMutationVariables = Exact<{ documentId: Scalars['ID']['input']; @@ -667,9 +669,9 @@ export type UpdateCustomerMutationVariables = Exact<{ }>; -export type UpdateCustomerMutation = { __typename?: 'Mutation', updateCustomer?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined }; +export type UpdateCustomerMutation = { __typename?: 'Mutation', updateCustomer?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined }; -export type OrderFieldsFragment = { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type OrderFieldsFragment = { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; export type GetOrdersQueryVariables = Exact<{ filters?: InputMaybe; @@ -678,21 +680,21 @@ export type GetOrdersQueryVariables = Exact<{ }>; -export type GetOrdersQuery = { __typename?: 'Query', orders: Array<{ __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined> }; +export type GetOrdersQuery = { __typename?: 'Query', orders: Array<{ __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined> }; export type GetOrderQueryVariables = Exact<{ documentId: Scalars['ID']['input']; }>; -export type GetOrderQuery = { __typename?: 'Query', order?: { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined }; +export type GetOrderQuery = { __typename?: 'Query', order?: { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined }; export type CreateOrderMutationVariables = Exact<{ input: OrderInput; }>; -export type CreateOrderMutation = { __typename?: 'Mutation', createOrder?: { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined }; +export type CreateOrderMutation = { __typename?: 'Mutation', createOrder?: { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined }; export type UpdateOrderMutationVariables = Exact<{ documentId: Scalars['ID']['input']; @@ -700,30 +702,30 @@ export type UpdateOrderMutationVariables = Exact<{ }>; -export type UpdateOrderMutation = { __typename?: 'Mutation', updateOrder?: { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined }; +export type UpdateOrderMutation = { __typename?: 'Mutation', updateOrder?: { __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined }; -export type ServiceFieldsFragment = { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined }; +export type ServiceFieldsFragment = { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined }; export type GetServicesQueryVariables = Exact<{ filters?: InputMaybe; }>; -export type GetServicesQuery = { __typename?: 'Query', services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined> }; +export type GetServicesQuery = { __typename?: 'Query', services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined> }; export type GetServiceQueryVariables = Exact<{ documentId: Scalars['ID']['input']; }>; -export type GetServiceQuery = { __typename?: 'Query', service?: { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type GetServiceQuery = { __typename?: 'Query', service?: { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; export type CreateServiceMutationVariables = Exact<{ data: ServiceInput; }>; -export type CreateServiceMutation = { __typename?: 'Mutation', createService?: { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type CreateServiceMutation = { __typename?: 'Mutation', createService?: { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; export type UpdateServiceMutationVariables = Exact<{ documentId: Scalars['ID']['input']; @@ -731,37 +733,37 @@ export type UpdateServiceMutationVariables = Exact<{ }>; -export type UpdateServiceMutation = { __typename?: 'Mutation', updateService?: { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type UpdateServiceMutation = { __typename?: 'Mutation', updateService?: { __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; -export type SlotFieldsFragment = { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined }; +export type SlotFieldsFragment = { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined }; export type CreateSlotMutationVariables = Exact<{ input: SlotInput; }>; -export type CreateSlotMutation = { __typename?: 'Mutation', createSlot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type CreateSlotMutation = { __typename?: 'Mutation', createSlot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; export type GetSlotsQueryVariables = Exact<{ filters?: InputMaybe; }>; -export type GetSlotsQuery = { __typename?: 'Query', slots: Array<{ __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined> }; +export type GetSlotsQuery = { __typename?: 'Query', slots: Array<{ __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined> }; export type GetSlotsOrdersQueryVariables = Exact<{ filters?: InputMaybe; }>; -export type GetSlotsOrdersQuery = { __typename?: 'Query', slots: Array<{ __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, orders: Array<{ __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined>, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined> }; +export type GetSlotsOrdersQuery = { __typename?: 'Query', slots: Array<{ __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, orders: Array<{ __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined>, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined> }; export type GetSlotQueryVariables = Exact<{ documentId: Scalars['ID']['input']; }>; -export type GetSlotQuery = { __typename?: 'Query', slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, orders: Array<{ __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined>, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type GetSlotQuery = { __typename?: 'Query', slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, orders: Array<{ __typename?: 'Order', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Order_State | null | undefined, order_number?: number | null | undefined, services: Array<{ __typename?: 'Service', documentId: string, name: string, description?: string | null | undefined, price?: number | null | undefined, active?: boolean | null | undefined, duration: string, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined>, client?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined, slot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined } | null | undefined>, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; export type UpdateSlotMutationVariables = Exact<{ documentId: Scalars['ID']['input']; @@ -769,7 +771,7 @@ export type UpdateSlotMutationVariables = Exact<{ }>; -export type UpdateSlotMutation = { __typename?: 'Mutation', updateSlot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; +export type UpdateSlotMutation = { __typename?: 'Mutation', updateSlot?: { __typename?: 'Slot', documentId: string, datetime_start: string, datetime_end: string, state?: Enum_Slot_State | null | undefined, master?: { __typename?: 'Customer', active?: boolean | null | undefined, bannedUntil?: string | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: number | null | undefined } | null | undefined } | null | undefined }; export type DeleteSlotMutationVariables = Exact<{ documentId: Scalars['ID']['input']; @@ -778,28 +780,28 @@ export type DeleteSlotMutationVariables = Exact<{ export type DeleteSlotMutation = { __typename?: 'Mutation', deleteSlot?: { __typename?: 'DeleteMutationResponse', documentId: string } | null | undefined }; -export const CustomerFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const ServiceFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const SlotFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const OrderFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const CustomerFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const ServiceFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const SlotFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const OrderFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; export const RegisterDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Register"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"password"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"register"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"username"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jwt"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]}}]}}]} as unknown as DocumentNode; export const LoginDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Login"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"password"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"login"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"identifier"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jwt"}}]}}]}}]} as unknown as DocumentNode; export const CreateCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"role"},"value":{"kind":"EnumValue","value":"client"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}}]}}]}}]} as unknown as DocumentNode; -export const GetCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"or"},"value":{"kind":"ListValue","values":[{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"documentId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}]}}]}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const GetMastersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMasters"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"or"},"value":{"kind":"ListValue","values":[{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"documentId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}]}}]}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"masters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const GetClientsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetClients"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"or"},"value":{"kind":"ListValue","values":[{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"clients"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const UpdateCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CustomerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; -export const GetOrdersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOrders"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderFiltersInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationArg"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sort"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"orders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sort"}}},{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; -export const GetOrderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOrder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"order"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; -export const CreateOrderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOrder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrder"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; -export const UpdateOrderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOrder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOrder"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; -export const GetServicesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetServices"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ServiceFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"services"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"name:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; -export const GetServiceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetService"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"service"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; -export const CreateServiceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateService"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServiceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createService"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; -export const UpdateServiceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateService"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServiceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateService"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; -export const CreateSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createSlot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; -export const GetSlotsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSlots"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slots"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; -export const GetSlotsOrdersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSlotsOrders"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slots"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}},{"kind":"Field","name":{"kind":"Name","value":"orders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; -export const GetSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"orders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; -export const UpdateSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateSlot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"or"},"value":{"kind":"ListValue","values":[{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"documentId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}]}}]}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const GetMastersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMasters"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"or"},"value":{"kind":"ListValue","values":[{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"documentId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}]}}]}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"masters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const GetClientsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetClients"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"or"},"value":{"kind":"ListValue","values":[{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}}]}}]},{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"clients"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const UpdateCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CustomerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode; +export const GetOrdersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOrders"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderFiltersInput"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"PaginationArg"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sort"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"orders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sort"}}},{"kind":"Argument","name":{"kind":"Name","value":"pagination"},"value":{"kind":"Variable","name":{"kind":"Name","value":"pagination"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetOrderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOrder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"order"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; +export const CreateOrderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOrder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrder"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; +export const UpdateOrderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOrder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"OrderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOrder"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetServicesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetServices"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ServiceFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"services"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"name:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetServiceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetService"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"service"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const CreateServiceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateService"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServiceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createService"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const UpdateServiceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateService"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServiceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateService"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const CreateSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createSlot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetSlotsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSlots"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slots"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetSlotsOrdersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSlotsOrders"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filters"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotFiltersInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slots"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filters"}}},{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}},{"kind":"Field","name":{"kind":"Name","value":"orders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; +export const GetSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"slot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"orders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"sort"},"value":{"kind":"StringValue","value":"datetime_start:asc","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"OrderFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServiceFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Service"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"price"}},{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"OrderFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Order"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"order_number"}},{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServiceFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"client"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}},{"kind":"Field","name":{"kind":"Name","value":"slot"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}}]} as unknown as DocumentNode; +export const UpdateSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SlotInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateSlot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"SlotFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"bannedUntil"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SlotFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Slot"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_start"}},{"kind":"Field","name":{"kind":"Name","value":"datetime_end"}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"master"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerFields"}}]}}]}}]} as unknown as DocumentNode; export const DeleteSlotDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteSlot"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteSlot"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"documentId"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/packages/utils/src/customer.ts b/packages/utils/src/customer.ts index 2b1686d..6b9962f 100644 --- a/packages/utils/src/customer.ts +++ b/packages/utils/src/customer.ts @@ -1,5 +1,9 @@ import * as GQL from '../../graphql/types'; +export function isCustomerBanned(customer: GQL.CustomerFieldsFragment): boolean { + return Boolean(customer.bannedUntil && new Date() < new Date(customer.bannedUntil)); +} + export function isCustomerMaster(customer: GQL.CustomerFieldsFragment) { return customer?.role === GQL.Enum_Customer_Role.Master; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0a03f4..6054bc9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,17 +13,17 @@ catalogs: specifier: ^20 version: 20.17.8 '@types/react': - specifier: ^19 - version: 19.1.8 + specifier: ^19.1.11 + version: 19.1.11 '@types/react-dom': - specifier: ^19 - version: 19.1.2 + specifier: ^19.1.8 + version: 19.1.8 '@vchikalkin/eslint-config-awesome': specifier: ^2.2.2 version: 2.2.2 autoprefixer: specifier: ^10.4.20 - version: 10.4.20 + version: 10.4.21 dayjs: specifier: ^1.11.3 version: 1.11.13 @@ -35,7 +35,7 @@ catalogs: version: 9.21.0 graphql: specifier: ^16.9.0 - version: 16.9.0 + version: 16.11.0 husky: specifier: ^9.1.7 version: 9.1.7 @@ -44,13 +44,13 @@ catalogs: version: 9.0.2 lint-staged: specifier: ^15.2.10 - version: 15.2.10 + version: 15.5.2 lucide-react: specifier: ^0.462.0 version: 0.462.0 postcss: specifier: ^8.4.49 - version: 8.4.49 + version: 8.5.6 postcss-load-config: specifier: ^6.0.1 version: 6.0.1 @@ -59,31 +59,28 @@ catalogs: version: 3.6.2 radashi: specifier: ^12.5.1 - version: 12.5.1 + version: 12.6.0 react: - specifier: ^19 - version: 19.1.0 + specifier: ^19.1.1 + version: 19.1.1 react-dom: - specifier: ^19 - version: 19.1.0 + specifier: ^19.1.1 + version: 19.1.1 tailwindcss: specifier: ^3.4.15 - version: 3.4.15 - telegraf: - specifier: ^4.16.3 - version: 4.16.3 + version: 3.4.17 typescript: specifier: ^5.7 - version: 5.7.2 + version: 5.8.3 vite-tsconfig-paths: specifier: ^5.1.4 version: 5.1.4 vitest: specifier: ^2.1.8 - version: 2.1.8 + version: 2.1.9 zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.25.71 importers: @@ -105,6 +102,36 @@ importers: apps/bot: dependencies: + '@grammyjs/auto-chat-action': + specifier: ^0.1.1 + version: 0.1.1(grammy@1.38.1) + '@grammyjs/commands': + specifier: ^1.2.0 + version: 1.2.0(grammy@1.38.1) + '@grammyjs/conversations': + specifier: ^2.1.0 + version: 2.1.0(grammy@1.38.1) + '@grammyjs/hydrate': + specifier: ^1.6.0 + version: 1.6.0(grammy@1.38.1) + '@grammyjs/i18n': + specifier: ^1.1.2 + version: 1.1.2(grammy@1.38.1) + '@grammyjs/parse-mode': + specifier: ^2.2.0 + version: 2.2.0(grammy@1.38.1) + '@grammyjs/ratelimiter': + specifier: ^1.2.1 + version: 1.2.1 + '@grammyjs/runner': + specifier: ^2.0.3 + version: 2.0.3(grammy@1.38.1) + '@grammyjs/storage-redis': + specifier: ^2.5.1 + version: 2.5.1 + '@grammyjs/types': + specifier: ^3.22.1 + version: 3.22.1 '@repo/graphql': specifier: workspace:* version: link:../../packages/graphql @@ -114,9 +141,18 @@ importers: '@types/node': specifier: 'catalog:' version: 20.19.4 - telegraf: - specifier: 'catalog:' - version: 4.16.3 + grammy: + specifier: ^1.38.1 + version: 1.38.1 + ioredis: + specifier: ^5.7.0 + version: 5.7.0 + pino: + specifier: ^9.9.0 + version: 9.9.0 + pino-pretty: + specifier: ^13.1.1 + version: 13.1.1 tsup: specifier: ^8.5.0 version: 8.5.0(jiti@2.4.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.0) @@ -162,22 +198,22 @@ importers: version: link:../../packages/utils '@tanstack/react-query': specifier: ^5.64.1 - version: 5.64.1(react@19.1.0) + version: 5.64.1(react@19.1.1) '@telegram-apps/sdk-react': specifier: ^2.0.19 - version: 2.0.19(@types/react@19.1.8)(react@19.1.0) + version: 2.0.19(@types/react@19.1.11)(react@19.1.1) '@testing-library/react': specifier: ^16.1.0 - version: 16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@types/node': specifier: 'catalog:' version: 20.17.8 '@types/react': specifier: 'catalog:' - version: 19.1.8 + version: 19.1.11 '@types/react-dom': specifier: 'catalog:' - version: 19.1.2(@types/react@19.1.8) + version: 19.1.8(@types/react@19.1.11) '@vitejs/plugin-react': specifier: ^4.3.4 version: 4.3.4(vite@5.4.19(@types/node@20.17.8)) @@ -198,19 +234,19 @@ importers: version: 25.0.1 lucide-react: specifier: 'catalog:' - version: 0.462.0(react@19.1.0) + version: 0.462.0(react@19.1.1) next: - specifier: 15.3.4 - version: 15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: ^15.5.0 + version: 15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) next-auth: specifier: ^4.24.11 - version: 4.24.11(next@15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 4.24.11(next@15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1) next-intl: specifier: ^3.26.0 - version: 3.26.0(next@15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) + version: 3.26.0(next@15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1) next-themes: specifier: ^0.4.4 - version: 0.4.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 0.4.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) postcss: specifier: 'catalog:' version: 8.4.49 @@ -219,10 +255,10 @@ importers: version: 12.5.1 react: specifier: 'catalog:' - version: 19.1.0 + version: 19.1.1 react-dom: specifier: 'catalog:' - version: 19.1.0(react@19.1.0) + version: 19.1.1(react@19.1.1) tailwindcss: specifier: 'catalog:' version: 3.4.15 @@ -231,7 +267,7 @@ importers: version: 5.7.2 use-debounce: specifier: ^10.0.4 - version: 10.0.4(react@19.1.0) + version: 10.0.4(react@19.1.1) vite-tsconfig-paths: specifier: 'catalog:' version: 5.1.4(typescript@5.7.2)(vite@5.4.19(@types/node@20.17.8)) @@ -243,7 +279,7 @@ importers: version: 3.24.1 zustand: specifier: ^5.0.3 - version: 5.0.3(@types/react@19.1.8)(react@19.1.0) + version: 5.0.3(@types/react@19.1.11)(react@19.1.1) devDependencies: '@repo/eslint-config': specifier: workspace:* @@ -277,7 +313,7 @@ importers: dependencies: '@apollo/client': specifier: 'catalog:' - version: 3.13.8(@types/react@19.1.8)(graphql-ws@5.16.0(graphql@16.11.0))(graphql@16.11.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 3.13.8(@types/react@19.1.11)(graphql-ws@5.16.0(graphql@16.11.0))(graphql@16.11.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.11.0) @@ -336,31 +372,31 @@ importers: dependencies: '@radix-ui/react-avatar': specifier: ^1.1.2 - version: 1.1.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.1.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-checkbox': specifier: ^1.1.3 - version: 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-dropdown-menu': specifier: ^2.1.4 - version: 2.1.4(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.1.4(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-label': specifier: ^2.1.1 - version: 2.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-scroll-area': specifier: ^1.2.2 - version: 1.2.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.2.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-select': specifier: ^2.1.4 - version: 2.1.4(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.1.4(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-slot': specifier: ^1.1.1 - version: 1.1.1(@types/react@19.1.8)(react@19.1.0) + version: 1.1.1(@types/react@19.1.11)(react@19.1.1) '@repo/typescript-config': specifier: workspace:* version: link:../typescript-config '@types/react': specifier: 'catalog:' - version: 19.1.8 + version: 19.1.11 autoprefixer: specifier: 'catalog:' version: 10.4.21(postcss@8.5.6) @@ -375,10 +411,10 @@ importers: version: 4.1.0 lucide-react: specifier: 'catalog:' - version: 0.462.0(react@19.1.0) + version: 0.462.0(react@19.1.1) next-themes: specifier: ^0.4.4 - version: 0.4.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 0.4.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) postcss: specifier: 'catalog:' version: 8.5.6 @@ -387,16 +423,16 @@ importers: version: 6.0.1(jiti@2.4.1)(postcss@8.5.6)(tsx@4.19.2)(yaml@2.8.0) react: specifier: 'catalog:' - version: 19.1.0 + version: 19.1.1 react-day-picker: specifier: 8.10.1 - version: 8.10.1(date-fns@4.1.0)(react@19.1.0) + version: 8.10.1(date-fns@4.1.0)(react@19.1.1) react-dom: specifier: 'catalog:' - version: 19.1.0(react@19.1.0) + version: 19.1.1(react@19.1.1) sonner: specifier: ^1.7.4 - version: 1.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.7.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1) tailwind-merge: specifier: ^2.5.5 version: 2.5.5 @@ -781,11 +817,17 @@ packages: '@bundled-es-modules/tough-cookie@0.1.6': resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} + '@deno/shim-deno-test@0.5.0': + resolution: {integrity: sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==} + + '@deno/shim-deno@0.18.2': + resolution: {integrity: sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA==} + '@emnapi/core@1.4.3': resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} - '@emnapi/runtime@1.4.3': - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + '@emnapi/runtime@1.4.5': + resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==} '@emnapi/wasi-threads@1.0.2': resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} @@ -1275,6 +1317,14 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + '@fluent/bundle@0.17.1': + resolution: {integrity: sha512-CRFNT9QcSFAeFDneTF59eyv3JXFGhIIN4boUO2y22YmsuuKLyDk+N1I/NQUYz9Ab63e6V7T6vItoZIG/2oOOuw==} + engines: {node: '>=12.0.0', npm: '>=7.0.0'} + + '@fluent/langneg@0.6.2': + resolution: {integrity: sha512-YF4gZ4sLYRQfctpUR2uhb5UyPUYY5n/bi3OaED/Q4awKjPjlaF8tInO3uja7pnLQcmLTURkZL7L9zxv2Z5NDwg==} + engines: {node: '>=12.0.0', npm: '>=7.0.0'} + '@formatjs/ecma402-abstract@2.3.1': resolution: {integrity: sha512-Ip9uV+/MpLXWRk03U/GzeJMuPeOXpJBSB5V1tjA6kJhvqssye5J5LoYLc7Z5IAHb7nR62sRoguzrFiVCP/hnzw==} @@ -1290,6 +1340,55 @@ packages: '@formatjs/intl-localematcher@0.5.9': resolution: {integrity: sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA==} + '@grammyjs/auto-chat-action@0.1.1': + resolution: {integrity: sha512-70Jdy+keIri4452tluaZpKtHag5gD8pNczoXqajsnsx7pJC5wg3DAQ5unpt0xJb8KsVBAGWuJb298SBl3TVecg==} + peerDependencies: + grammy: ^1.0.0 + + '@grammyjs/commands@1.2.0': + resolution: {integrity: sha512-np3uZElWtVIQk8w73szBXcubuKFOEGnp+4dHyhw+KeVsN/yVwuaEAxt+kyEhfTUQdNH0zU7ffuCM2l7lVUDBWw==} + peerDependencies: + grammy: ^1.17.1 + + '@grammyjs/conversations@2.1.0': + resolution: {integrity: sha512-nYoHwFyXcQ2lkQejKReoINknkgFjeIZhyJNMBwHng5UHO/ewHKs1dV2XVaLrKkHTZ1gCZ+dKkjEp26wwHyQeGg==} + engines: {node: ^12.20.0 || >=14.13.1} + peerDependencies: + grammy: ^1.20.1 + + '@grammyjs/hydrate@1.6.0': + resolution: {integrity: sha512-dpszYCuzrYhhSJNjwV+zhG9SpwfFkO6nk+IHa56cd8ZCLO//aVVHOO5vKeobq4chhDu+MYjn7KaQMp0sn4Lb/g==} + engines: {node: ^12.20.0 || >=14.13.1} + peerDependencies: + grammy: ^1.38.0 + + '@grammyjs/i18n@1.1.2': + resolution: {integrity: sha512-PcK06mxuDDZjxdZ5HywBhr+erEITsR816KP4DNIDDds1jpA45pfz/nS9FdZmzF8H6lMyPix3mV5WL1rT4q+BuA==} + engines: {node: '>=12'} + peerDependencies: + grammy: ^1.10.0 + + '@grammyjs/parse-mode@2.2.0': + resolution: {integrity: sha512-sI5xjXYn1ihEEf1bJx4ew2KPsX1O3jsd2V/MpA1CX2tCYlxquidr7agk4IOR5bGEK38pyNVxVBdyCiy/eMxEfQ==} + engines: {node: '>=14.13.1'} + peerDependencies: + grammy: ^1.36.1 + + '@grammyjs/ratelimiter@1.2.1': + resolution: {integrity: sha512-4bmVUBCBnIb2epbDiBLCvvnVjaYg7kDCPR1Ptt6gqoxm5vlD8BjainYv+yjF6221hu2KUv8QAckumDI+6xyGsQ==} + + '@grammyjs/runner@2.0.3': + resolution: {integrity: sha512-nckmTs1dPWfVQteK9cxqxzE+0m1VRvluLWB8UgFzsjg62w3qthPJt0TYtJBEdG7OedvfQq4vnFAyE6iaMkR42A==} + engines: {node: '>=12.20.0 || >=14.13.1'} + peerDependencies: + grammy: ^1.13.1 + + '@grammyjs/storage-redis@2.5.1': + resolution: {integrity: sha512-Rz7bnrtDz8NOjgSRR4n/rBciHKSvmkrgIUc+8Yb96tSsecBlA91MGOmcgmQXKxb7gTmwliF37VgmMT85bsCZtA==} + + '@grammyjs/types@3.22.1': + resolution: {integrity: sha512-QJX0Y8lpjE+/nuTKGmxybKmvdrLHV7gqbhI/UXoWlJLWtowbwk+oW+ngfHKwegD+ewL2SX8+tQo/1E14Ma0qlw==} + '@graphql-codegen/add@5.0.3': resolution: {integrity: sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==} peerDependencies: @@ -1618,112 +1717,124 @@ packages: resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} engines: {node: '>=18.18'} - '@img/sharp-darwin-arm64@0.34.1': - resolution: {integrity: sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==} + '@img/sharp-darwin-arm64@0.34.3': + resolution: {integrity: sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.34.1': - resolution: {integrity: sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==} + '@img/sharp-darwin-x64@0.34.3': + resolution: {integrity: sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [darwin] - '@img/sharp-libvips-darwin-arm64@1.1.0': - resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} + '@img/sharp-libvips-darwin-arm64@1.2.0': + resolution: {integrity: sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==} cpu: [arm64] os: [darwin] - '@img/sharp-libvips-darwin-x64@1.1.0': - resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} + '@img/sharp-libvips-darwin-x64@1.2.0': + resolution: {integrity: sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==} cpu: [x64] os: [darwin] - '@img/sharp-libvips-linux-arm64@1.1.0': - resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} + '@img/sharp-libvips-linux-arm64@1.2.0': + resolution: {integrity: sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linux-arm@1.1.0': - resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} + '@img/sharp-libvips-linux-arm@1.2.0': + resolution: {integrity: sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==} cpu: [arm] os: [linux] - '@img/sharp-libvips-linux-ppc64@1.1.0': - resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==} + '@img/sharp-libvips-linux-ppc64@1.2.0': + resolution: {integrity: sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==} cpu: [ppc64] os: [linux] - '@img/sharp-libvips-linux-s390x@1.1.0': - resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} + '@img/sharp-libvips-linux-s390x@1.2.0': + resolution: {integrity: sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==} cpu: [s390x] os: [linux] - '@img/sharp-libvips-linux-x64@1.1.0': - resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} + '@img/sharp-libvips-linux-x64@1.2.0': + resolution: {integrity: sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==} cpu: [x64] os: [linux] - '@img/sharp-libvips-linuxmusl-arm64@1.1.0': - resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} + '@img/sharp-libvips-linuxmusl-arm64@1.2.0': + resolution: {integrity: sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==} cpu: [arm64] os: [linux] - '@img/sharp-libvips-linuxmusl-x64@1.1.0': - resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} + '@img/sharp-libvips-linuxmusl-x64@1.2.0': + resolution: {integrity: sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==} cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.34.1': - resolution: {integrity: sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==} + '@img/sharp-linux-arm64@0.34.3': + resolution: {integrity: sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.34.1': - resolution: {integrity: sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==} + '@img/sharp-linux-arm@0.34.3': + resolution: {integrity: sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - '@img/sharp-linux-s390x@0.34.1': - resolution: {integrity: sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==} + '@img/sharp-linux-ppc64@0.34.3': + resolution: {integrity: sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.3': + resolution: {integrity: sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.34.1': - resolution: {integrity: sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==} + '@img/sharp-linux-x64@0.34.3': + resolution: {integrity: sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.34.1': - resolution: {integrity: sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==} + '@img/sharp-linuxmusl-arm64@0.34.3': + resolution: {integrity: sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.34.1': - resolution: {integrity: sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==} + '@img/sharp-linuxmusl-x64@0.34.3': + resolution: {integrity: sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.34.1': - resolution: {integrity: sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==} + '@img/sharp-wasm32@0.34.3': + resolution: {integrity: sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [wasm32] - '@img/sharp-win32-ia32@0.34.1': - resolution: {integrity: sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==} + '@img/sharp-win32-arm64@0.34.3': + resolution: {integrity: sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.3': + resolution: {integrity: sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.34.1': - resolution: {integrity: sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==} + '@img/sharp-win32-x64@0.34.3': + resolution: {integrity: sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [win32] @@ -1759,6 +1870,9 @@ packages: '@types/node': optional: true + '@ioredis/commands@1.3.0': + resolution: {integrity: sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==} + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -1799,8 +1913,8 @@ packages: '@napi-rs/wasm-runtime@0.2.11': resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} - '@next/env@15.3.4': - resolution: {integrity: sha512-ZkdYzBseS6UjYzz6ylVKPOK+//zLWvD6Ta+vpoye8cW11AjiQjGYVibF0xuvT4L0iJfAPfZLFidaEzAOywyOAQ==} + '@next/env@15.5.0': + resolution: {integrity: sha512-sDaprBAfzCQiOgo2pO+LhnV0Wt2wBgartjrr+dpcTORYVnnXD0gwhHhiiyIih9hQbq+JnbqH4odgcFWhqCGidw==} '@next/eslint-plugin-next@14.2.18': resolution: {integrity: sha512-KyYTbZ3GQwWOjX3Vi1YcQbekyGP0gdammb7pbmmi25HBUCINzDReyrzCMOJIeZisK1Q3U6DT5Rlc4nm2/pQeXA==} @@ -1808,50 +1922,50 @@ packages: '@next/eslint-plugin-next@15.0.3': resolution: {integrity: sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw==} - '@next/swc-darwin-arm64@15.3.4': - resolution: {integrity: sha512-z0qIYTONmPRbwHWvpyrFXJd5F9YWLCsw3Sjrzj2ZvMYy9NPQMPZ1NjOJh4ojr4oQzcGYwgJKfidzehaNa1BpEg==} + '@next/swc-darwin-arm64@15.5.0': + resolution: {integrity: sha512-v7Jj9iqC6enxIRBIScD/o0lH7QKvSxq2LM8UTyqJi+S2w2QzhMYjven4vgu/RzgsdtdbpkyCxBTzHl/gN5rTRg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.3.4': - resolution: {integrity: sha512-Z0FYJM8lritw5Wq+vpHYuCIzIlEMjewG2aRkc3Hi2rcbULknYL/xqfpBL23jQnCSrDUGAo/AEv0Z+s2bff9Zkw==} + '@next/swc-darwin-x64@15.5.0': + resolution: {integrity: sha512-s2Nk6ec+pmYmAb/utawuURy7uvyYKDk+TRE5aqLRsdnj3AhwC9IKUBmhfnLmY/+P+DnwqpeXEFIKe9tlG0p6CA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.3.4': - resolution: {integrity: sha512-l8ZQOCCg7adwmsnFm8m5q9eIPAHdaB2F3cxhufYtVo84pymwKuWfpYTKcUiFcutJdp9xGHC+F1Uq3xnFU1B/7g==} + '@next/swc-linux-arm64-gnu@15.5.0': + resolution: {integrity: sha512-mGlPJMZReU4yP5fSHjOxiTYvZmwPSWn/eF/dcg21pwfmiUCKS1amFvf1F1RkLHPIMPfocxLViNWFvkvDB14Isg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.3.4': - resolution: {integrity: sha512-wFyZ7X470YJQtpKot4xCY3gpdn8lE9nTlldG07/kJYexCUpX1piX+MBfZdvulo+t1yADFVEuzFfVHfklfEx8kw==} + '@next/swc-linux-arm64-musl@15.5.0': + resolution: {integrity: sha512-biWqIOE17OW/6S34t1X8K/3vb1+svp5ji5QQT/IKR+VfM3B7GvlCwmz5XtlEan2ukOUf9tj2vJJBffaGH4fGRw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.3.4': - resolution: {integrity: sha512-gEbH9rv9o7I12qPyvZNVTyP/PWKqOp8clvnoYZQiX800KkqsaJZuOXkWgMa7ANCCh/oEN2ZQheh3yH8/kWPSEg==} + '@next/swc-linux-x64-gnu@15.5.0': + resolution: {integrity: sha512-zPisT+obYypM/l6EZ0yRkK3LEuoZqHaSoYKj+5jiD9ESHwdr6QhnabnNxYkdy34uCigNlWIaCbjFmQ8FY5AlxA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.3.4': - resolution: {integrity: sha512-Cf8sr0ufuC/nu/yQ76AnarbSAXcwG/wj+1xFPNbyNo8ltA6kw5d5YqO8kQuwVIxk13SBdtgXrNyom3ZosHAy4A==} + '@next/swc-linux-x64-musl@15.5.0': + resolution: {integrity: sha512-+t3+7GoU9IYmk+N+FHKBNFdahaReoAktdOpXHFIPOU1ixxtdge26NgQEEkJkCw2dHT9UwwK5zw4mAsURw4E8jA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.3.4': - resolution: {integrity: sha512-ay5+qADDN3rwRbRpEhTOreOn1OyJIXS60tg9WMYTWCy3fB6rGoyjLVxc4dR9PYjEdR2iDYsaF5h03NA+XuYPQQ==} + '@next/swc-win32-arm64-msvc@15.5.0': + resolution: {integrity: sha512-d8MrXKh0A+c9DLiy1BUFwtg3Hu90Lucj3k6iKTUdPOv42Ve2UiIG8HYi3UAb8kFVluXxEfdpCoPPCSODk5fDcw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.3.4': - resolution: {integrity: sha512-4kDt31Bc9DGyYs41FTL1/kNpDeHyha2TC0j5sRRoKCyrhNcfZ/nRQkAUlF27mETwm8QyHqIjHJitfcza2Iykfg==} + '@next/swc-win32-x64-msvc@15.5.0': + resolution: {integrity: sha512-Fe1tGHxOWEyQjmygWkkXSwhFcTJuimrNu52JEuwItrKJVV4iRjbWp9I7zZjwqtiNnQmxoEvoisn8wueFLrNpvQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2367,9 +2481,6 @@ packages: peerDependencies: eslint: '>=8.40.0' - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -2381,9 +2492,6 @@ packages: peerDependencies: react: ^18 || ^19 - '@telegraf/types@7.1.0': - resolution: {integrity: sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==} - '@telegram-apps/bridge@1.7.1': resolution: {integrity: sha512-oRbznpIC4UibMVygQ+tcS0ZSKx7DaI07MXQF42VETQ/VOCKeaWZeQFUifo4A+CzT6XMGo2hyse/CQP9ziX0H7g==} @@ -2481,13 +2589,13 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/react-dom@19.1.2': - resolution: {integrity: sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==} + '@types/react-dom@19.1.8': + resolution: {integrity: sha512-xG7xaBMJCpcK0RpN8jDbAACQo54ycO6h4dSSmgv8+fu6ZIAdANkx/WsawASUjVXYfy+J9AbUpRMNNEsXCDfDBQ==} peerDependencies: '@types/react': ^19.0.0 - '@types/react@19.1.8': - resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} + '@types/react@19.1.11': + resolution: {integrity: sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ==} '@types/statuses@2.0.6': resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} @@ -2951,6 +3059,10 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + auto-bind@4.0.0: resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} engines: {node: '>=8'} @@ -3029,18 +3141,9 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - buffer-alloc-unsafe@1.1.0: - resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} - - buffer-alloc@1.2.0: - resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} - buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} - buffer-fill@1.0.0: - resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} - buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -3208,6 +3311,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -3349,6 +3456,9 @@ packages: date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} @@ -3419,6 +3529,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + dependency-graph@0.11.0: resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} engines: {node: '>= 0.6.0'} @@ -3431,8 +3545,8 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} detect-node-es@1.1.0: @@ -3507,6 +3621,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + enhance-visitors@1.0.0: resolution: {integrity: sha512-+29eJLiUixTEDRaZ35Vu8jP3gPLNcQQkQkOQjLp2X+6cZGGPDD/uasbFzvLsJKnGZnvmyZ0srxudwOtskHeIDA==} engines: {node: '>=4.0.0'} @@ -3969,6 +4086,9 @@ packages: resolution: {integrity: sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==} engines: {node: ^12.20 || >= 14.13} + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} @@ -4003,6 +4123,13 @@ packages: fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fast-url-parser@1.1.3: resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} @@ -4204,6 +4331,10 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + grammy@1.38.1: + resolution: {integrity: sha512-aVBMeyYUjZ+rUEI+aV0T4himboXGs8Uf57c+vhtmHplPfgaRT04dyT9pG8R/GAmKeTUPh84GKO0u9IvaEGN6RA==} + engines: {node: ^12.20.0 || >=14.13.1} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -4304,6 +4435,9 @@ packages: headers-polyfill@4.0.3: resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -4395,6 +4529,10 @@ packages: invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + ioredis@5.7.0: + resolution: {integrity: sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==} + engines: {node: '>=12.22.0'} + is-absolute@1.0.0: resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} engines: {node: '>=0.10.0'} @@ -4628,6 +4766,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + isomorphic-ws@5.0.0: resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} peerDependencies: @@ -4803,6 +4945,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. @@ -4810,6 +4955,9 @@ packages: lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} @@ -4977,10 +5125,6 @@ packages: mlly@1.7.4: resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} - mri@1.2.0: - resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} - engines: {node: '>=4'} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -5056,13 +5200,13 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@15.3.4: - resolution: {integrity: sha512-mHKd50C+mCjam/gcnwqL1T1vPx/XQNFlXqFIVdgQdVAFY9iIQtY0IfaVflEYzKiqjeA7B0cYYMaCrmAYFjs4rA==} + next@15.5.0: + resolution: {integrity: sha512-N1lp9Hatw3a9XLt0307lGB4uTKsXDhyOKQo7uYMzX4i0nF/c27grcGXkLdb7VcT8QPYLBa8ouIyEoUQJ2OyeNQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.41.2 + '@playwright/test': ^1.51.1 babel-plugin-react-compiler: '*' react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 @@ -5178,6 +5322,10 @@ packages: resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} engines: {node: ^10.13.0 || >=12.0.0} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5238,10 +5386,6 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} - p-timeout@4.1.0: - resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==} - engines: {node: '>=10'} - p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -5346,6 +5490,20 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-pretty@13.1.1: + resolution: {integrity: sha512-TNNEOg0eA0u+/WuqH0MH0Xui7uqVk9D74ESOpjtebSQYbNWJk/dIxCXIxFsNfeN53JmtWqYHP2OrIZjT/CBEnA==} + hasBin: true + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.9.0: + resolution: {integrity: sha512-zxsRIQG9HzG+jEljmvmZupOMDUQ0Jpj0yAgE28jQvvrdYTlEaiGwelJpdndMl/MBuRr70heIj83QyqJUWaU8mQ==} + hasBin: true + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -5470,6 +5628,9 @@ packages: pretty-format@3.8.0: resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + promise@7.3.1: resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} @@ -5483,6 +5644,9 @@ packages: psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode@1.4.1: resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} @@ -5503,6 +5667,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + radashi@12.5.1: resolution: {integrity: sha512-gcznSPJe2SCIuWf6QTqSHZRyMQU6hnUk4NpR7LmmNmdK1BGOXdnHuNIO4VzNw+feu0Wsnv/AYmxqwUYDBatPMA==} engines: {node: '>=16.0.0'} @@ -5523,10 +5690,10 @@ packages: date-fns: ^2.28.0 || ^3.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom@19.1.0: - resolution: {integrity: sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==} + react-dom@19.1.1: + resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} peerDependencies: - react: ^19.1.0 + react: ^19.1.1 react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -5568,8 +5735,8 @@ packages: '@types/react': optional: true - react@19.1.0: - resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} + react@19.1.1: + resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -5595,10 +5762,22 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + recast@0.23.9: resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} engines: {node: '>= 4'} + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + refa@0.12.1: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -5739,9 +5918,6 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-compare@1.1.4: - resolution: {integrity: sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==} - safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -5761,10 +5937,6 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sandwich-stream@2.0.2: - resolution: {integrity: sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==} - engines: {node: '>= 0.10'} - saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -5779,6 +5951,9 @@ packages: scuid@1.1.0: resolution: {integrity: sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==} + secure-json-parse@4.0.0: + resolution: {integrity: sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==} + semver-compare@1.0.0: resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} @@ -5821,8 +5996,8 @@ packages: setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - sharp@0.34.1: - resolution: {integrity: sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==} + sharp@0.34.3: + resolution: {integrity: sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@2.0.0: @@ -5899,6 +6074,9 @@ packages: snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + sonner@1.7.4: resolution: {integrity: sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw==} peerDependencies: @@ -5916,6 +6094,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -5932,6 +6111,10 @@ packages: spdx-license-ids@3.0.20: resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + sponge-case@1.0.1: resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} @@ -5945,6 +6128,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -6038,6 +6224,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + styled-jsx@5.1.6: resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} engines: {node: '>= 12.0.0'} @@ -6104,11 +6294,6 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - telegraf@4.16.3: - resolution: {integrity: sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==} - engines: {node: ^12.20.0 || >=14.13.1} - hasBin: true - thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -6116,6 +6301,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -6639,6 +6827,11 @@ packages: engines: {node: '>= 8'} hasBin: true + which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -6796,7 +6989,7 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@apollo/client@3.13.8(@types/react@19.1.8)(graphql-ws@5.16.0(graphql@16.11.0))(graphql@16.11.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@apollo/client@3.13.8(@types/react@19.1.11)(graphql-ws@5.16.0(graphql@16.11.0))(graphql@16.11.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.11.0) '@wry/caches': 1.0.1 @@ -6807,15 +7000,15 @@ snapshots: hoist-non-react-statics: 3.3.2 optimism: 0.18.1 prop-types: 15.8.1 - rehackt: 0.1.0(@types/react@19.1.8)(react@19.1.0) + rehackt: 0.1.0(@types/react@19.1.11)(react@19.1.1) symbol-observable: 4.0.0 ts-invariant: 0.10.3 tslib: 2.8.1 zen-observable-ts: 1.2.5 optionalDependencies: graphql-ws: 5.16.0(graphql@16.11.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) transitivePeerDependencies: - '@types/react' @@ -7214,13 +7407,20 @@ snapshots: tough-cookie: 4.1.4 optional: true + '@deno/shim-deno-test@0.5.0': {} + + '@deno/shim-deno@0.18.2': + dependencies: + '@deno/shim-deno-test': 0.5.0 + which: 4.0.0 + '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.4.3': + '@emnapi/runtime@1.4.5': dependencies: tslib: 2.8.1 optional: true @@ -7462,7 +7662,7 @@ snapshots: '@eslint/config-array@0.19.2': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.0 + debug: 4.4.1 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -7474,7 +7674,7 @@ snapshots: '@eslint/eslintrc@3.3.0': dependencies: ajv: 6.12.6 - debug: 4.4.0 + debug: 4.4.1 espree: 10.3.0 globals: 14.0.0 ignore: 5.3.2 @@ -7503,14 +7703,18 @@ snapshots: '@floating-ui/core': 1.6.9 '@floating-ui/utils': 0.2.9 - '@floating-ui/react-dom@2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@floating-ui/react-dom@2.1.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@floating-ui/dom': 1.6.13 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) '@floating-ui/utils@0.2.9': {} + '@fluent/bundle@0.17.1': {} + + '@fluent/langneg@0.6.2': {} + '@formatjs/ecma402-abstract@2.3.1': dependencies: '@formatjs/fast-memoize': 2.2.5 @@ -7537,6 +7741,45 @@ snapshots: dependencies: tslib: 2.8.1 + '@grammyjs/auto-chat-action@0.1.1(grammy@1.38.1)': + dependencies: + grammy: 1.38.1 + + '@grammyjs/commands@1.2.0(grammy@1.38.1)': + dependencies: + grammy: 1.38.1 + + '@grammyjs/conversations@2.1.0(grammy@1.38.1)': + dependencies: + grammy: 1.38.1 + + '@grammyjs/hydrate@1.6.0(grammy@1.38.1)': + dependencies: + abort-controller: 3.0.0 + grammy: 1.38.1 + + '@grammyjs/i18n@1.1.2(grammy@1.38.1)': + dependencies: + '@deno/shim-deno': 0.18.2 + '@fluent/bundle': 0.17.1 + '@fluent/langneg': 0.6.2 + grammy: 1.38.1 + + '@grammyjs/parse-mode@2.2.0(grammy@1.38.1)': + dependencies: + grammy: 1.38.1 + + '@grammyjs/ratelimiter@1.2.1': {} + + '@grammyjs/runner@2.0.3(grammy@1.38.1)': + dependencies: + abort-controller: 3.0.0 + grammy: 1.38.1 + + '@grammyjs/storage-redis@2.5.1': {} + + '@grammyjs/types@3.22.1': {} + '@graphql-codegen/add@5.0.3(graphql@16.11.0)': dependencies: '@graphql-codegen/plugin-helpers': 5.1.0(graphql@16.11.0) @@ -8175,82 +8418,90 @@ snapshots: '@humanwhocodes/retry@0.4.2': {} - '@img/sharp-darwin-arm64@0.34.1': + '@img/sharp-darwin-arm64@0.34.3': optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.1.0 + '@img/sharp-libvips-darwin-arm64': 1.2.0 optional: true - '@img/sharp-darwin-x64@0.34.1': + '@img/sharp-darwin-x64@0.34.3': optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.1.0 + '@img/sharp-libvips-darwin-x64': 1.2.0 optional: true - '@img/sharp-libvips-darwin-arm64@1.1.0': + '@img/sharp-libvips-darwin-arm64@1.2.0': optional: true - '@img/sharp-libvips-darwin-x64@1.1.0': + '@img/sharp-libvips-darwin-x64@1.2.0': optional: true - '@img/sharp-libvips-linux-arm64@1.1.0': + '@img/sharp-libvips-linux-arm64@1.2.0': optional: true - '@img/sharp-libvips-linux-arm@1.1.0': + '@img/sharp-libvips-linux-arm@1.2.0': optional: true - '@img/sharp-libvips-linux-ppc64@1.1.0': + '@img/sharp-libvips-linux-ppc64@1.2.0': optional: true - '@img/sharp-libvips-linux-s390x@1.1.0': + '@img/sharp-libvips-linux-s390x@1.2.0': optional: true - '@img/sharp-libvips-linux-x64@1.1.0': + '@img/sharp-libvips-linux-x64@1.2.0': optional: true - '@img/sharp-libvips-linuxmusl-arm64@1.1.0': + '@img/sharp-libvips-linuxmusl-arm64@1.2.0': optional: true - '@img/sharp-libvips-linuxmusl-x64@1.1.0': + '@img/sharp-libvips-linuxmusl-x64@1.2.0': optional: true - '@img/sharp-linux-arm64@0.34.1': + '@img/sharp-linux-arm64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.1.0 + '@img/sharp-libvips-linux-arm64': 1.2.0 optional: true - '@img/sharp-linux-arm@0.34.1': + '@img/sharp-linux-arm@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.1.0 + '@img/sharp-libvips-linux-arm': 1.2.0 optional: true - '@img/sharp-linux-s390x@0.34.1': + '@img/sharp-linux-ppc64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.1.0 + '@img/sharp-libvips-linux-ppc64': 1.2.0 optional: true - '@img/sharp-linux-x64@0.34.1': + '@img/sharp-linux-s390x@0.34.3': optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.1.0 + '@img/sharp-libvips-linux-s390x': 1.2.0 optional: true - '@img/sharp-linuxmusl-arm64@0.34.1': + '@img/sharp-linux-x64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 + '@img/sharp-libvips-linux-x64': 1.2.0 optional: true - '@img/sharp-linuxmusl-x64@0.34.1': + '@img/sharp-linuxmusl-arm64@0.34.3': optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.1.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 optional: true - '@img/sharp-wasm32@0.34.1': + '@img/sharp-linuxmusl-x64@0.34.3': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.0 + optional: true + + '@img/sharp-wasm32@0.34.3': dependencies: - '@emnapi/runtime': 1.4.3 + '@emnapi/runtime': 1.4.5 optional: true - '@img/sharp-win32-ia32@0.34.1': + '@img/sharp-win32-arm64@0.34.3': optional: true - '@img/sharp-win32-x64@0.34.1': + '@img/sharp-win32-ia32@0.34.3': + optional: true + + '@img/sharp-win32-x64@0.34.3': optional: true '@inquirer/confirm@5.1.13(@types/node@20.17.8)': @@ -8310,6 +8561,8 @@ snapshots: '@types/node': 24.0.10 optional: true + '@ioredis/commands@1.3.0': {} + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -8357,11 +8610,11 @@ snapshots: '@napi-rs/wasm-runtime@0.2.11': dependencies: '@emnapi/core': 1.4.3 - '@emnapi/runtime': 1.4.3 + '@emnapi/runtime': 1.4.5 '@tybys/wasm-util': 0.9.0 optional: true - '@next/env@15.3.4': {} + '@next/env@15.5.0': {} '@next/eslint-plugin-next@14.2.18': dependencies: @@ -8371,28 +8624,28 @@ snapshots: dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.3.4': + '@next/swc-darwin-arm64@15.5.0': optional: true - '@next/swc-darwin-x64@15.3.4': + '@next/swc-darwin-x64@15.5.0': optional: true - '@next/swc-linux-arm64-gnu@15.3.4': + '@next/swc-linux-arm64-gnu@15.5.0': optional: true - '@next/swc-linux-arm64-musl@15.3.4': + '@next/swc-linux-arm64-musl@15.5.0': optional: true - '@next/swc-linux-x64-gnu@15.3.4': + '@next/swc-linux-x64-gnu@15.5.0': optional: true - '@next/swc-linux-x64-musl@15.3.4': + '@next/swc-linux-x64-musl@15.5.0': optional: true - '@next/swc-win32-arm64-msvc@15.3.4': + '@next/swc-win32-arm64-msvc@15.5.0': optional: true - '@next/swc-win32-x64-msvc@15.3.4': + '@next/swc-win32-x64-msvc@15.5.0': optional: true '@nodelib/fs.scandir@2.1.5': @@ -8454,331 +8707,331 @@ snapshots: '@radix-ui/primitive@1.1.1': {} - '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-arrow@1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-avatar@1.1.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-avatar@1.1.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-checkbox@1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-checkbox@1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-previous': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-collection@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-collection@1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.1.1(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-slot': 1.1.1(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-compose-refs@1.1.1(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-compose-refs@1.1.1(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-context@1.1.1(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-context@1.1.1(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-direction@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-direction@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dismissable-layer@1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-dropdown-menu@2.1.4(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dropdown-menu@2.1.4(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-menu': 2.1.4(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-id': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-menu': 2.1.4(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-focus-guards@1.1.1(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-focus-guards@1.1.1(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-focus-scope@1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-id@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-id@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-label@2.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-label@2.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-menu@2.1.4(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-menu@2.1.4(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-direction': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-id': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-roving-focus': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-slot': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) aria-hidden: 1.2.4 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - react-remove-scroll: 2.6.2(@types/react@19.1.8)(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-remove-scroll: 2.6.2(@types/react@19.1.11)(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-popper@1.2.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-popper@1.2.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-rect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-size': 1.1.0(@types/react@19.1.8)(react@19.1.0) + '@floating-ui/react-dom': 2.1.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-arrow': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-rect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-size': 1.1.0(@types/react@19.1.11)(react@19.1.1) '@radix-ui/rect': 1.1.0 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-portal@1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-portal@1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-presence@1.1.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-presence@1.1.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-primitive@2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-slot': 1.1.1(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-slot': 1.1.1(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-roving-focus@1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-direction': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-id': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-scroll-area@1.2.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-scroll-area@1.2.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-direction': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-presence': 1.1.2(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-select@2.1.4(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-select@2.1.4(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/number': 1.1.0 '@radix-ui/primitive': 1.1.1 - '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-context': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-direction': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-id': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.1.1(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-use-previous': 1.1.0(@types/react@19.1.8)(react@19.1.0) - '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-collection': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-context': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-direction': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-dismissable-layer': 1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-focus-scope': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-id': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-popper': 1.2.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-portal': 1.1.3(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-slot': 1.1.1(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-use-previous': 1.1.0(@types/react@19.1.11)(react@19.1.1) + '@radix-ui/react-visually-hidden': 1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) aria-hidden: 1.2.4 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - react-remove-scroll: 2.6.2(@types/react@19.1.8)(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + react-remove-scroll: 2.6.2(@types/react@19.1.11)(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) - '@radix-ui/react-slot@1.1.1(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-slot@1.1.1(@types/react@19.1.11)(react@19.1.1)': dependencies: - '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 + '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-previous@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-previous@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-rect@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-rect@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: '@radix-ui/rect': 1.1.0 - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-use-size@1.1.0(@types/react@19.1.8)(react@19.1.0)': + '@radix-ui/react-use-size@1.1.0(@types/react@19.1.11)(react@19.1.1)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.8)(react@19.1.0) - react: 19.1.0 + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.1.11)(react@19.1.1) + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-visually-hidden@1.1.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: - '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + '@radix-ui/react-primitive': 2.0.1(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) '@radix-ui/rect@1.1.0': {} @@ -8858,20 +9111,16 @@ snapshots: - supports-color - typescript - '@swc/counter@0.1.3': {} - '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 '@tanstack/query-core@5.64.1': {} - '@tanstack/react-query@5.64.1(react@19.1.0)': + '@tanstack/react-query@5.64.1(react@19.1.1)': dependencies: '@tanstack/query-core': 5.64.1 - react: 19.1.0 - - '@telegraf/types@7.1.0': {} + react: 19.1.1 '@telegram-apps/bridge@1.7.1': dependencies: @@ -8886,12 +9135,12 @@ snapshots: '@telegram-apps/signals': 1.1.0 '@telegram-apps/toolkit': 1.0.0 - '@telegram-apps/sdk-react@2.0.19(@types/react@19.1.8)(react@19.1.0)': + '@telegram-apps/sdk-react@2.0.19(@types/react@19.1.11)(react@19.1.1)': dependencies: '@telegram-apps/sdk': 2.9.1 - react: 19.1.0 + react: 19.1.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 '@telegram-apps/sdk@2.9.1': dependencies: @@ -8923,15 +9172,15 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/react@16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.2(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@testing-library/react@16.1.0(@testing-library/dom@10.4.0)(@types/react-dom@19.1.8(@types/react@19.1.11))(@types/react@19.1.11)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@babel/runtime': 7.26.0 '@testing-library/dom': 10.4.0 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 - '@types/react-dom': 19.1.2(@types/react@19.1.8) + '@types/react': 19.1.11 + '@types/react-dom': 19.1.8(@types/react@19.1.11) '@tybys/wasm-util@0.9.0': dependencies: @@ -8990,11 +9239,11 @@ snapshots: '@types/normalize-package-data@2.4.4': {} - '@types/react-dom@19.1.2(@types/react@19.1.8)': + '@types/react-dom@19.1.8(@types/react@19.1.11)': dependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - '@types/react@19.1.8': + '@types/react@19.1.11': dependencies: csstype: 3.1.3 @@ -9541,6 +9790,8 @@ snapshots: asynckit@0.4.0: {} + atomic-sleep@1.0.0: {} + auto-bind@4.0.0: {} autoprefixer@10.4.20(postcss@8.4.49): @@ -9651,17 +9902,8 @@ snapshots: dependencies: node-int64: 0.4.0 - buffer-alloc-unsafe@1.1.0: {} - - buffer-alloc@1.2.0: - dependencies: - buffer-alloc-unsafe: 1.1.0 - buffer-fill: 1.0.0 - buffer-equal-constant-time@1.0.1: {} - buffer-fill@1.0.0: {} - buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -9856,6 +10098,8 @@ snapshots: clsx@2.1.1: {} + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -10001,6 +10245,8 @@ snapshots: date-fns@4.1.0: {} + dateformat@4.6.3: {} + dayjs@1.11.13: {} debounce@1.2.1: {} @@ -10047,13 +10293,15 @@ snapshots: delayed-stream@1.0.0: {} + denque@2.1.0: {} + dependency-graph@0.11.0: {} dequal@2.0.3: {} detect-indent@6.1.0: {} - detect-libc@2.0.3: + detect-libc@2.0.4: optional: true detect-node-es@1.1.0: {} @@ -10118,6 +10366,10 @@ snapshots: emoji-regex@9.2.2: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + enhance-visitors@1.0.0: dependencies: lodash: 4.17.21 @@ -10928,6 +11180,8 @@ snapshots: extract-files@11.0.0: {} + fast-copy@3.0.2: {} + fast-decode-uri-component@1.0.1: {} fast-deep-equal@3.1.3: {} @@ -10970,6 +11224,10 @@ snapshots: dependencies: fast-decode-uri-component: 1.0.1 + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + fast-url-parser@1.1.3: dependencies: punycode: 1.4.1 @@ -11199,6 +11457,16 @@ snapshots: graceful-fs@4.2.11: {} + grammy@1.38.1: + dependencies: + '@grammyjs/types': 3.22.1 + abort-controller: 3.0.0 + debug: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + - supports-color + graphemer@1.4.0: {} graphql-config@4.5.0(@types/node@24.0.10)(graphql@16.11.0): @@ -11306,6 +11574,8 @@ snapshots: headers-polyfill@4.0.3: optional: true + help-me@5.0.0: {} + hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -11409,6 +11679,20 @@ snapshots: dependencies: loose-envify: 1.4.0 + ioredis@5.7.0: + dependencies: + '@ioredis/commands': 1.3.0 + cluster-key-slot: 1.1.2 + debug: 4.4.1 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + is-absolute@1.0.0: dependencies: is-relative: 1.0.0 @@ -11642,6 +11926,8 @@ snapshots: isexe@2.0.0: {} + isexe@3.1.1: {} + isomorphic-ws@5.0.0(ws@8.13.0): dependencies: ws: 8.13.0 @@ -11864,10 +12150,14 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.defaults@4.2.0: {} + lodash.get@4.4.2: {} lodash.includes@4.3.0: {} + lodash.isarguments@3.1.0: {} + lodash.isboolean@3.0.3: {} lodash.isinteger@4.0.4: {} @@ -11938,9 +12228,9 @@ snapshots: dependencies: yallist: 4.0.0 - lucide-react@0.462.0(react@19.1.0): + lucide-react@0.462.0(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 lz-string@1.5.0: {} @@ -12008,8 +12298,6 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.1 - mri@1.2.0: {} - ms@2.1.3: {} msw@2.7.0(@types/node@20.17.8)(typescript@5.7.2): @@ -12087,56 +12375,54 @@ snapshots: negotiator@1.0.0: {} - next-auth@4.24.11(next@15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next-auth@4.24.11(next@15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: '@babel/runtime': 7.26.0 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + next: 15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) oauth: 0.9.15 openid-client: 5.7.1 preact: 10.25.3 preact-render-to-string: 5.2.6(preact@10.25.3) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) uuid: 8.3.2 - next-intl@3.26.0(next@15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0): + next-intl@3.26.0(next@15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react@19.1.1): dependencies: '@formatjs/intl-localematcher': 0.5.9 negotiator: 1.0.0 - next: 15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - use-intl: 3.26.0(react@19.1.0) + next: 15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + react: 19.1.1 + use-intl: 3.26.0(react@19.1.1) - next-themes@0.4.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next-themes@0.4.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) - next@15.3.4(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + next@15.5.0(@babel/core@7.26.0)(@playwright/test@1.49.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: - '@next/env': 15.3.4 - '@swc/counter': 0.1.3 + '@next/env': 15.5.0 '@swc/helpers': 0.5.15 - busboy: 1.6.0 caniuse-lite: 1.0.30001726 postcss: 8.4.31 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - styled-jsx: 5.1.6(@babel/core@7.26.0)(react@19.1.0) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + styled-jsx: 5.1.6(@babel/core@7.26.0)(react@19.1.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.3.4 - '@next/swc-darwin-x64': 15.3.4 - '@next/swc-linux-arm64-gnu': 15.3.4 - '@next/swc-linux-arm64-musl': 15.3.4 - '@next/swc-linux-x64-gnu': 15.3.4 - '@next/swc-linux-x64-musl': 15.3.4 - '@next/swc-win32-arm64-msvc': 15.3.4 - '@next/swc-win32-x64-msvc': 15.3.4 + '@next/swc-darwin-arm64': 15.5.0 + '@next/swc-darwin-x64': 15.5.0 + '@next/swc-linux-arm64-gnu': 15.5.0 + '@next/swc-linux-arm64-musl': 15.5.0 + '@next/swc-linux-x64-gnu': 15.5.0 + '@next/swc-linux-x64-musl': 15.5.0 + '@next/swc-win32-arm64-msvc': 15.5.0 + '@next/swc-win32-x64-msvc': 15.5.0 '@playwright/test': 1.49.1 - sharp: 0.34.1 + sharp: 0.34.3 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -12237,6 +12523,8 @@ snapshots: oidc-token-hash@5.0.3: {} + on-exit-leak-free@2.1.2: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -12319,8 +12607,6 @@ snapshots: dependencies: aggregate-error: 3.1.0 - p-timeout@4.1.0: {} - p-try@2.2.0: {} param-case@3.0.4: @@ -12408,6 +12694,42 @@ snapshots: pify@2.3.0: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.1.1: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.3 + secure-json-parse: 4.0.0 + sonic-boom: 4.2.0 + strip-json-comments: 5.0.3 + + pino-std-serializers@7.0.0: {} + + pino@9.9.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.6: {} pkg-dir@5.0.0: @@ -12537,6 +12859,8 @@ snapshots: pretty-format@3.8.0: {} + process-warning@5.0.0: {} + promise@7.3.1: dependencies: asap: 2.0.6 @@ -12554,6 +12878,11 @@ snapshots: punycode: 2.3.1 optional: true + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode@1.4.1: {} punycode@2.3.1: {} @@ -12569,6 +12898,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + radashi@12.5.1: {} radashi@12.6.0: {} @@ -12577,14 +12908,14 @@ snapshots: ramda@0.30.1: {} - react-day-picker@8.10.1(date-fns@4.1.0)(react@19.1.0): + react-day-picker@8.10.1(date-fns@4.1.0)(react@19.1.1): dependencies: date-fns: 4.1.0 - react: 19.1.0 + react: 19.1.1 - react-dom@19.1.0(react@19.1.0): + react-dom@19.1.1(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 scheduler: 0.26.0 react-is@16.13.1: {} @@ -12593,34 +12924,34 @@ snapshots: react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.8(@types/react@19.1.8)(react@19.1.0): + react-remove-scroll-bar@2.3.8(@types/react@19.1.11)(react@19.1.1): dependencies: - react: 19.1.0 - react-style-singleton: 2.2.3(@types/react@19.1.8)(react@19.1.0) + react: 19.1.1 + react-style-singleton: 2.2.3(@types/react@19.1.11)(react@19.1.1) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - react-remove-scroll@2.6.2(@types/react@19.1.8)(react@19.1.0): + react-remove-scroll@2.6.2(@types/react@19.1.11)(react@19.1.1): dependencies: - react: 19.1.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.1.8)(react@19.1.0) - react-style-singleton: 2.2.3(@types/react@19.1.8)(react@19.1.0) + react: 19.1.1 + react-remove-scroll-bar: 2.3.8(@types/react@19.1.11)(react@19.1.1) + react-style-singleton: 2.2.3(@types/react@19.1.11)(react@19.1.1) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.1.8)(react@19.1.0) - use-sidecar: 1.1.3(@types/react@19.1.8)(react@19.1.0) + use-callback-ref: 1.3.3(@types/react@19.1.11)(react@19.1.1) + use-sidecar: 1.1.3(@types/react@19.1.11)(react@19.1.1) optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - react-style-singleton@2.2.3(@types/react@19.1.8)(react@19.1.0): + react-style-singleton@2.2.3(@types/react@19.1.11)(react@19.1.1): dependencies: get-nonce: 1.0.1 - react: 19.1.0 + react: 19.1.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - react@19.1.0: {} + react@19.1.1: {} read-cache@1.0.0: dependencies: @@ -12651,6 +12982,8 @@ snapshots: readdirp@4.1.2: {} + real-require@0.2.0: {} + recast@0.23.9: dependencies: ast-types: 0.16.1 @@ -12659,6 +12992,12 @@ snapshots: tiny-invariant: 1.3.3 tslib: 2.8.1 + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + refa@0.12.1: dependencies: '@eslint-community/regexpp': 4.12.1 @@ -12704,10 +13043,10 @@ snapshots: dependencies: jsesc: 0.5.0 - rehackt@0.1.0(@types/react@19.1.8)(react@19.1.0): + rehackt@0.1.0(@types/react@19.1.11)(react@19.1.1): optionalDependencies: - '@types/react': 19.1.8 - react: 19.1.0 + '@types/react': 19.1.11 + react: 19.1.1 relay-runtime@12.0.0: dependencies: @@ -12827,10 +13166,6 @@ snapshots: safe-buffer@5.2.1: {} - safe-compare@1.1.4: - dependencies: - buffer-alloc: 1.2.0 - safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -12852,8 +13187,6 @@ snapshots: safer-buffer@2.1.2: {} - sandwich-stream@2.0.2: {} - saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -12868,6 +13201,8 @@ snapshots: scuid@1.1.0: {} + secure-json-parse@4.0.0: {} + semver-compare@1.0.0: {} semver@5.7.2: {} @@ -12910,32 +13245,34 @@ snapshots: setimmediate@1.0.5: {} - sharp@0.34.1: + sharp@0.34.3: dependencies: color: 4.2.3 - detect-libc: 2.0.3 + detect-libc: 2.0.4 semver: 7.7.2 optionalDependencies: - '@img/sharp-darwin-arm64': 0.34.1 - '@img/sharp-darwin-x64': 0.34.1 - '@img/sharp-libvips-darwin-arm64': 1.1.0 - '@img/sharp-libvips-darwin-x64': 1.1.0 - '@img/sharp-libvips-linux-arm': 1.1.0 - '@img/sharp-libvips-linux-arm64': 1.1.0 - '@img/sharp-libvips-linux-ppc64': 1.1.0 - '@img/sharp-libvips-linux-s390x': 1.1.0 - '@img/sharp-libvips-linux-x64': 1.1.0 - '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 - '@img/sharp-libvips-linuxmusl-x64': 1.1.0 - '@img/sharp-linux-arm': 0.34.1 - '@img/sharp-linux-arm64': 0.34.1 - '@img/sharp-linux-s390x': 0.34.1 - '@img/sharp-linux-x64': 0.34.1 - '@img/sharp-linuxmusl-arm64': 0.34.1 - '@img/sharp-linuxmusl-x64': 0.34.1 - '@img/sharp-wasm32': 0.34.1 - '@img/sharp-win32-ia32': 0.34.1 - '@img/sharp-win32-x64': 0.34.1 + '@img/sharp-darwin-arm64': 0.34.3 + '@img/sharp-darwin-x64': 0.34.3 + '@img/sharp-libvips-darwin-arm64': 1.2.0 + '@img/sharp-libvips-darwin-x64': 1.2.0 + '@img/sharp-libvips-linux-arm': 1.2.0 + '@img/sharp-libvips-linux-arm64': 1.2.0 + '@img/sharp-libvips-linux-ppc64': 1.2.0 + '@img/sharp-libvips-linux-s390x': 1.2.0 + '@img/sharp-libvips-linux-x64': 1.2.0 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.0 + '@img/sharp-libvips-linuxmusl-x64': 1.2.0 + '@img/sharp-linux-arm': 0.34.3 + '@img/sharp-linux-arm64': 0.34.3 + '@img/sharp-linux-ppc64': 0.34.3 + '@img/sharp-linux-s390x': 0.34.3 + '@img/sharp-linux-x64': 0.34.3 + '@img/sharp-linuxmusl-arm64': 0.34.3 + '@img/sharp-linuxmusl-x64': 0.34.3 + '@img/sharp-wasm32': 0.34.3 + '@img/sharp-win32-arm64': 0.34.3 + '@img/sharp-win32-ia32': 0.34.3 + '@img/sharp-win32-x64': 0.34.3 optional: true shebang-command@2.0.0: @@ -13025,10 +13362,14 @@ snapshots: dot-case: 3.0.4 tslib: 2.6.3 - sonner@1.7.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + sonic-boom@4.2.0: dependencies: - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) + atomic-sleep: 1.0.0 + + sonner@1.7.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + dependencies: + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) source-map-js@1.2.1: {} @@ -13057,6 +13398,8 @@ snapshots: spdx-license-ids@3.0.20: {} + split2@4.2.0: {} + sponge-case@1.0.1: dependencies: tslib: 2.6.3 @@ -13067,6 +13410,8 @@ snapshots: stackback@0.0.2: {} + standard-as-callback@2.1.0: {} + statuses@2.0.2: optional: true @@ -13186,10 +13531,12 @@ snapshots: strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(@babel/core@7.26.0)(react@19.1.0): + strip-json-comments@5.0.3: {} + + styled-jsx@5.1.6(@babel/core@7.26.0)(react@19.1.1): dependencies: client-only: 0.0.1 - react: 19.1.0 + react: 19.1.1 optionalDependencies: '@babel/core': 7.26.0 @@ -13288,20 +13635,6 @@ snapshots: tapable@2.2.1: {} - telegraf@4.16.3: - dependencies: - '@telegraf/types': 7.1.0 - abort-controller: 3.0.0 - debug: 4.4.1 - mri: 1.2.0 - node-fetch: 2.7.0 - p-timeout: 4.1.0 - safe-compare: 1.1.4 - sandwich-stream: 2.0.2 - transitivePeerDependencies: - - encoding - - supports-color - thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -13310,6 +13643,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + through@2.3.8: {} tiny-invariant@1.3.3: {} @@ -13636,30 +13973,30 @@ snapshots: urlpattern-polyfill@8.0.2: {} - use-callback-ref@1.3.3(@types/react@19.1.8)(react@19.1.0): + use-callback-ref@1.3.3(@types/react@19.1.11)(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 - use-debounce@10.0.4(react@19.1.0): + use-debounce@10.0.4(react@19.1.1): dependencies: - react: 19.1.0 + react: 19.1.1 - use-intl@3.26.0(react@19.1.0): + use-intl@3.26.0(react@19.1.1): dependencies: '@formatjs/fast-memoize': 2.2.5 intl-messageformat: 10.7.10 - react: 19.1.0 + react: 19.1.1 - use-sidecar@1.1.3(@types/react@19.1.8)(react@19.1.0): + use-sidecar@1.1.3(@types/react@19.1.11)(react@19.1.1): dependencies: detect-node-es: 1.1.0 - react: 19.1.0 + react: 19.1.1 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.8 + '@types/react': 19.1.11 util-deprecate@1.0.2: {} @@ -13944,6 +14281,10 @@ snapshots: dependencies: isexe: 2.0.0 + which@4.0.0: + dependencies: + isexe: 3.1.1 + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 @@ -14053,7 +14394,7 @@ snapshots: zod@3.25.71: {} - zustand@5.0.3(@types/react@19.1.8)(react@19.1.0): + zustand@5.0.3(@types/react@19.1.11)(react@19.1.1): optionalDependencies: - '@types/react': 19.1.8 - react: 19.1.0 + '@types/react': 19.1.11 + react: 19.1.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5a37920..2f0ca8f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,8 +4,8 @@ packages: catalog: "@apollo/client": ^3.12.4 "@types/node": ^20 - "@types/react": ^19 - "@types/react-dom": ^19 + "@types/react": ^19.1.11 + "@types/react-dom": ^19.1.8 "@vchikalkin/eslint-config-awesome": ^2.2.2 autoprefixer: ^10.4.20 dayjs: ^1.11.3 @@ -19,12 +19,11 @@ catalog: postcss: ^8.4.49 postcss-load-config: ^6.0.1 prettier: ^3.2.5 - react: ^19 - react-dom: ^19 + react: ^19.1.1 + react-dom: ^19.1.1 radashi: ^12.5.1 rimraf: ^6.0.1 tailwindcss: ^3.4.15 - telegraf: ^4.16.3 typescript: ^5.7 vite-tsconfig-paths: ^5.1.4 vitest: ^2.1.8