Showing preview only (3,118K chars total). Download the full file or copy to clipboard to get everything.
Repository: EvolutionAPI/evolution-api
Branch: main
Commit: cd800f2976e1
Files: 346
Total size: 2.9 MB
Directory structure:
gitextract_y8izy66h/
├── .cursor/
│ └── rules/
│ ├── README.md
│ ├── core-development.mdc
│ ├── cursor.json
│ ├── project-context.mdc
│ └── specialized-rules/
│ ├── controller-rules.mdc
│ ├── dto-rules.mdc
│ ├── guard-rules.mdc
│ ├── integration-channel-rules.mdc
│ ├── integration-chatbot-rules.mdc
│ ├── integration-event-rules.mdc
│ ├── integration-storage-rules.mdc
│ ├── route-rules.mdc
│ ├── service-rules.mdc
│ ├── type-rules.mdc
│ ├── util-rules.mdc
│ └── validate-rules.mdc
├── .dockerignore
├── .eslintignore
├── .eslintrc.js
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── -en--bug-report.yaml
│ │ ├── -en--feature-request.yaml
│ │ ├── -pt--reportar-bug.yaml
│ │ ├── -pt--solicitar-recurso.yaml
│ │ ├── bug_report.yml
│ │ └── feature_request.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── check_code_quality.yml
│ ├── publish_docker_image.yml
│ ├── publish_docker_image_homolog.yml
│ ├── publish_docker_image_latest.yml
│ └── security.yml
├── .gitignore
├── .gitmodules
├── .husky/
│ ├── README.md
│ ├── commit-msg
│ ├── pre-commit
│ └── pre-push
├── .prettierrc.js
├── .vscode/
│ └── settings.json
├── AGENTS.md
├── CHANGELOG.md
├── CLAUDE.md
├── Docker/
│ ├── kafka/
│ │ └── docker-compose.yaml
│ ├── minio/
│ │ └── docker-compose.yaml
│ ├── mysql/
│ │ └── docker-compose.yaml
│ ├── postgres/
│ │ └── docker-compose.yaml
│ ├── rabbitmq/
│ │ └── docker-compose.yaml
│ ├── redis/
│ │ └── docker-compose.yaml
│ ├── scripts/
│ │ ├── deploy_database.sh
│ │ ├── env_functions.sh
│ │ └── generate_database.sh
│ └── swarm/
│ └── evolution_api_v2.yaml
├── Dockerfile
├── Dockerfile.metrics
├── Extras/
│ └── chatwoot/
│ ├── configurar_admin.json
│ ├── criador_de_empresas.json
│ └── criador_de_inbox.json
├── LICENSE
├── README.md
├── SECURITY.md
├── commitlint.config.js
├── docker-compose.dev.yaml
├── docker-compose.yaml
├── env.example
├── grafana-dashboard.json.example
├── local_install.sh
├── manager/
│ └── dist/
│ ├── assets/
│ │ ├── index-CO3NSIFj.js
│ │ └── index-DsIrum0U.css
│ └── index.html
├── manager_install.sh
├── package.json
├── prisma/
│ ├── mysql-migrations/
│ │ ├── 20240809105427_init/
│ │ │ └── migration.sql
│ │ ├── 20240813153900_add_unique_index_for_remoted_jid_and_instance_in_contacts/
│ │ │ └── migration.sql
│ │ ├── 20240814173138_add_ignore_jids_chatwoot/
│ │ │ └── migration.sql
│ │ ├── 20240814214314_integrations_unification/
│ │ │ └── migration.sql
│ │ ├── 20240821203259_add_postgres_migrations/
│ │ │ └── migration.sql
│ │ ├── 20240824162012_add_type_on_integration_sessions/
│ │ │ └── migration.sql
│ │ ├── 20240825131301_change_to_evolution_bot/
│ │ │ └── migration.sql
│ │ ├── 20241001172800_add_message_status/
│ │ │ └── migration.sql
│ │ ├── 20241108101333_fix_message_status_as_string/
│ │ │ └── migration.sql
│ │ ├── 20250214181954_add_wavoip_token_column/
│ │ │ └── migration.sql
│ │ ├── 20250225180031_add_nats_integration/
│ │ │ └── migration.sql
│ │ ├── 20250510035200_add_wavoip_token_to_settings_table/
│ │ │ └── migration.sql
│ │ ├── 20250514232744_add_n8n_table/
│ │ │ └── migration.sql
│ │ ├── 20250515211815_add_evoai_table/
│ │ │ └── migration.sql
│ │ ├── 20250516012152_remove_unique_atribute_for_file_name_in_media/
│ │ │ └── migration.sql
│ │ ├── 20250612155048_add_coluns_trypebot_tables/
│ │ │ └── migration.sql
│ │ ├── 20250613143000_add_lid_column_to_is_onwhatsapp/
│ │ │ └── migration.sql
│ │ ├── 20250918183910_add_kafka_integration/
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ ├── mysql-schema.prisma
│ ├── postgresql-migrations/
│ │ ├── 20240609181238_init/
│ │ │ └── migration.sql
│ │ ├── 20240610144159_create_column_profile_name_instance/
│ │ │ └── migration.sql
│ │ ├── 20240611125754_create_columns_whitelabel_chatwoot/
│ │ │ └── migration.sql
│ │ ├── 20240611202817_create_columns_debounce_time_typebot/
│ │ │ └── migration.sql
│ │ ├── 20240712144948_add_business_id_column_to_instances/
│ │ │ └── migration.sql
│ │ ├── 20240712150256_create_templates_table/
│ │ │ └── migration.sql
│ │ ├── 20240712155950_adjusts_in_templates_table/
│ │ │ └── migration.sql
│ │ ├── 20240712162206_remove_templates_table/
│ │ │ └── migration.sql
│ │ ├── 20240712223655_column_fallback_typebot/
│ │ │ └── migration.sql
│ │ ├── 20240712230631_column_ignore_jids_typebot/
│ │ │ └── migration.sql
│ │ ├── 20240713184337_add_media_table/
│ │ │ └── migration.sql
│ │ ├── 20240718121437_add_openai_tables/
│ │ │ └── migration.sql
│ │ ├── 20240718123923_adjusts_openai_tables/
│ │ │ └── migration.sql
│ │ ├── 20240722173259_add_name_column_to_openai_creds/
│ │ │ └── migration.sql
│ │ ├── 20240722173518_add_name_column_to_openai_creds/
│ │ │ └── migration.sql
│ │ ├── 20240723152648_adjusts_in_column_openai_creds/
│ │ │ └── migration.sql
│ │ ├── 20240723200254_add_webhookurl_on_message/
│ │ │ └── migration.sql
│ │ ├── 20240725184147_create_template_table/
│ │ │ └── migration.sql
│ │ ├── 20240725202651_add_webhook_url_template_table/
│ │ │ └── migration.sql
│ │ ├── 20240725221646_modify_token_instance_table/
│ │ │ └── migration.sql
│ │ ├── 20240729115127_modify_trigger_type_openai_typebot_table/
│ │ │ └── migration.sql
│ │ ├── 20240729180347_modify_typebot_session_status_openai_typebot_table/
│ │ │ └── migration.sql
│ │ ├── 20240730152156_create_dify_tables/
│ │ │ └── migration.sql
│ │ ├── 20240801193907_add_column_speech_to_text_openai_setting_table/
│ │ │ └── migration.sql
│ │ ├── 20240803163908_add_column_description_on_integrations_table/
│ │ │ └── migration.sql
│ │ ├── 20240808210239_add_column_function_url_openaibot_table/
│ │ │ └── migration.sql
│ │ ├── 20240811021156_add_chat_name_column/
│ │ │ └── migration.sql
│ │ ├── 20240811183328_add_unique_index_for_remoted_jid_and_instance_in_contacts/
│ │ │ └── migration.sql
│ │ ├── 20240813003116_make_label_unique_for_instance/
│ │ │ └── migration.sql
│ │ ├── 20240814173033_add_ignore_jids_chatwoot/
│ │ │ └── migration.sql
│ │ ├── 20240814202359_integrations_unification/
│ │ │ └── migration.sql
│ │ ├── 20240817110155_add_trigger_type_advanced/
│ │ │ └── migration.sql
│ │ ├── 20240819154941_add_context_to_integration_session/
│ │ │ └── migration.sql
│ │ ├── 20240821120816_bot_id_integration_session/
│ │ │ └── migration.sql
│ │ ├── 20240821171327_add_generic_bot_table/
│ │ │ └── migration.sql
│ │ ├── 20240821194524_add_flowise_table/
│ │ │ └── migration.sql
│ │ ├── 20240824161333_add_type_on_integration_sessions/
│ │ │ └── migration.sql
│ │ ├── 20240825130616_change_to_evolution_bot/
│ │ │ └── migration.sql
│ │ ├── 20240828140837_add_is_on_whatsapp_table/
│ │ │ └── migration.sql
│ │ ├── 20240828141556_remove_name_column_from_on_whatsapp_table/
│ │ │ └── migration.sql
│ │ ├── 20240830193533_changed_table_case/
│ │ │ └── migration.sql
│ │ ├── 20240906202019_add_headers_on_webhook_config/
│ │ │ └── migration.sql
│ │ ├── 20241001180457_add_message_status/
│ │ │ └── migration.sql
│ │ ├── 20241006130306_alter_status_on_message_table/
│ │ │ └── migration.sql
│ │ ├── 20241007164026_add_unread_messages_on_chat_table/
│ │ │ └── migration.sql
│ │ ├── 20241011085129_create_pusher_table/
│ │ │ └── migration.sql
│ │ ├── 20241011100803_split_messages_and_time_per_char_integrations/
│ │ │ └── migration.sql
│ │ ├── 20241017144950_create_index/
│ │ │ └── migration.sql
│ │ ├── 20250116001415_add_wavoip_token_to_settings_table/
│ │ │ └── migration.sql
│ │ ├── 20250225180031_add_nats_integration/
│ │ │ └── migration.sql
│ │ ├── 20250514232744_add_n8n_table/
│ │ │ └── migration.sql
│ │ ├── 20250515211815_add_evoai_table/
│ │ │ └── migration.sql
│ │ ├── 20250516012152_remove_unique_atribute_for_file_name_in_media/
│ │ │ └── migration.sql
│ │ ├── 20250612155048_add_coluns_trypebot_tables/
│ │ │ └── migration.sql
│ │ ├── 20250613143000_add_lid_column_to_is_onwhatsapp/
│ │ │ └── migration.sql
│ │ ├── 20250918182355_add_kafka_integration/
│ │ │ └── migration.sql
│ │ ├── 20251122003044_add_chat_instance_remotejid_unique/
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ ├── postgresql-schema.prisma
│ └── psql_bouncer-schema.prisma
├── prometheus.yml.example
├── runWithProvider.js
├── src/
│ ├── @types/
│ │ └── express.d.ts
│ ├── api/
│ │ ├── abstract/
│ │ │ ├── abstract.cache.ts
│ │ │ ├── abstract.repository.ts
│ │ │ └── abstract.router.ts
│ │ ├── controllers/
│ │ │ ├── business.controller.ts
│ │ │ ├── call.controller.ts
│ │ │ ├── chat.controller.ts
│ │ │ ├── group.controller.ts
│ │ │ ├── instance.controller.ts
│ │ │ ├── label.controller.ts
│ │ │ ├── proxy.controller.ts
│ │ │ ├── sendMessage.controller.ts
│ │ │ ├── settings.controller.ts
│ │ │ └── template.controller.ts
│ │ ├── dto/
│ │ │ ├── business.dto.ts
│ │ │ ├── call.dto.ts
│ │ │ ├── chat.dto.ts
│ │ │ ├── chatbot.dto.ts
│ │ │ ├── group.dto.ts
│ │ │ ├── instance.dto.ts
│ │ │ ├── label.dto.ts
│ │ │ ├── proxy.dto.ts
│ │ │ ├── sendMessage.dto.ts
│ │ │ ├── settings.dto.ts
│ │ │ └── template.dto.ts
│ │ ├── guards/
│ │ │ ├── auth.guard.ts
│ │ │ ├── instance.guard.ts
│ │ │ └── telemetry.guard.ts
│ │ ├── integrations/
│ │ │ ├── channel/
│ │ │ │ ├── channel.controller.ts
│ │ │ │ ├── channel.router.ts
│ │ │ │ ├── evolution/
│ │ │ │ │ ├── evolution.channel.service.ts
│ │ │ │ │ ├── evolution.controller.ts
│ │ │ │ │ └── evolution.router.ts
│ │ │ │ ├── meta/
│ │ │ │ │ ├── meta.controller.ts
│ │ │ │ │ ├── meta.router.ts
│ │ │ │ │ └── whatsapp.business.service.ts
│ │ │ │ └── whatsapp/
│ │ │ │ ├── baileys.controller.ts
│ │ │ │ ├── baileys.router.ts
│ │ │ │ ├── baileysMessage.processor.ts
│ │ │ │ ├── voiceCalls/
│ │ │ │ │ ├── transport.type.ts
│ │ │ │ │ └── useVoiceCallsBaileys.ts
│ │ │ │ └── whatsapp.baileys.service.ts
│ │ │ ├── chatbot/
│ │ │ │ ├── base-chatbot.controller.ts
│ │ │ │ ├── base-chatbot.dto.ts
│ │ │ │ ├── base-chatbot.service.ts
│ │ │ │ ├── chatbot.controller.ts
│ │ │ │ ├── chatbot.router.ts
│ │ │ │ ├── chatbot.schema.ts
│ │ │ │ ├── chatwoot/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── chatwoot.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── chatwoot.dto.ts
│ │ │ │ │ ├── libs/
│ │ │ │ │ │ └── postgres.client.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── chatwoot.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── chatwoot.service.ts
│ │ │ │ │ ├── utils/
│ │ │ │ │ │ └── chatwoot-import-helper.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── chatwoot.schema.ts
│ │ │ │ ├── dify/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── dify.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── dify.dto.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── dify.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── dify.service.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── dify.schema.ts
│ │ │ │ ├── evoai/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── evoai.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── evoai.dto.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── evoai.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── evoai.service.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── evoai.schema.ts
│ │ │ │ ├── evolutionBot/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── evolutionBot.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── evolutionBot.dto.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── evolutionBot.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── evolutionBot.service.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── evolutionBot.schema.ts
│ │ │ │ ├── flowise/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── flowise.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── flowise.dto.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── flowise.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── flowise.service.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── flowise.schema.ts
│ │ │ │ ├── n8n/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── n8n.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── n8n.dto.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── n8n.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── n8n.service.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── n8n.schema.ts
│ │ │ │ ├── openai/
│ │ │ │ │ ├── controllers/
│ │ │ │ │ │ └── openai.controller.ts
│ │ │ │ │ ├── dto/
│ │ │ │ │ │ └── openai.dto.ts
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ └── openai.router.ts
│ │ │ │ │ ├── services/
│ │ │ │ │ │ └── openai.service.ts
│ │ │ │ │ └── validate/
│ │ │ │ │ └── openai.schema.ts
│ │ │ │ └── typebot/
│ │ │ │ ├── controllers/
│ │ │ │ │ └── typebot.controller.ts
│ │ │ │ ├── dto/
│ │ │ │ │ └── typebot.dto.ts
│ │ │ │ ├── routes/
│ │ │ │ │ └── typebot.router.ts
│ │ │ │ ├── services/
│ │ │ │ │ └── typebot.service.ts
│ │ │ │ └── validate/
│ │ │ │ └── typebot.schema.ts
│ │ │ ├── event/
│ │ │ │ ├── event.controller.ts
│ │ │ │ ├── event.dto.ts
│ │ │ │ ├── event.manager.ts
│ │ │ │ ├── event.router.ts
│ │ │ │ ├── event.schema.ts
│ │ │ │ ├── kafka/
│ │ │ │ │ ├── kafka.controller.ts
│ │ │ │ │ ├── kafka.router.ts
│ │ │ │ │ └── kafka.schema.ts
│ │ │ │ ├── nats/
│ │ │ │ │ ├── nats.controller.ts
│ │ │ │ │ └── nats.router.ts
│ │ │ │ ├── pusher/
│ │ │ │ │ ├── pusher.controller.ts
│ │ │ │ │ ├── pusher.router.ts
│ │ │ │ │ └── pusher.schema.ts
│ │ │ │ ├── rabbitmq/
│ │ │ │ │ ├── rabbitmq.controller.ts
│ │ │ │ │ └── rabbitmq.router.ts
│ │ │ │ ├── sqs/
│ │ │ │ │ ├── sqs.controller.ts
│ │ │ │ │ └── sqs.router.ts
│ │ │ │ ├── webhook/
│ │ │ │ │ ├── webhook.controller.ts
│ │ │ │ │ ├── webhook.router.ts
│ │ │ │ │ └── webhook.schema.ts
│ │ │ │ └── websocket/
│ │ │ │ ├── websocket.controller.ts
│ │ │ │ └── websocket.router.ts
│ │ │ ├── integration.dto.ts
│ │ │ └── storage/
│ │ │ ├── s3/
│ │ │ │ ├── controllers/
│ │ │ │ │ └── s3.controller.ts
│ │ │ │ ├── dto/
│ │ │ │ │ └── media.dto.ts
│ │ │ │ ├── libs/
│ │ │ │ │ └── minio.server.ts
│ │ │ │ ├── routes/
│ │ │ │ │ └── s3.router.ts
│ │ │ │ ├── services/
│ │ │ │ │ └── s3.service.ts
│ │ │ │ └── validate/
│ │ │ │ └── s3.schema.ts
│ │ │ └── storage.router.ts
│ │ ├── provider/
│ │ │ └── sessions.ts
│ │ ├── repository/
│ │ │ └── repository.service.ts
│ │ ├── routes/
│ │ │ ├── business.router.ts
│ │ │ ├── call.router.ts
│ │ │ ├── chat.router.ts
│ │ │ ├── group.router.ts
│ │ │ ├── index.router.ts
│ │ │ ├── instance.router.ts
│ │ │ ├── label.router.ts
│ │ │ ├── proxy.router.ts
│ │ │ ├── sendMessage.router.ts
│ │ │ ├── settings.router.ts
│ │ │ ├── template.router.ts
│ │ │ └── view.router.ts
│ │ ├── server.module.ts
│ │ ├── services/
│ │ │ ├── auth.service.ts
│ │ │ ├── cache.service.ts
│ │ │ ├── channel.service.ts
│ │ │ ├── monitor.service.ts
│ │ │ ├── proxy.service.ts
│ │ │ ├── settings.service.ts
│ │ │ └── template.service.ts
│ │ └── types/
│ │ └── wa.types.ts
│ ├── cache/
│ │ ├── cacheengine.ts
│ │ ├── localcache.ts
│ │ ├── rediscache.client.ts
│ │ └── rediscache.ts
│ ├── config/
│ │ ├── env.config.ts
│ │ ├── error.config.ts
│ │ ├── event.config.ts
│ │ ├── logger.config.ts
│ │ └── path.config.ts
│ ├── exceptions/
│ │ ├── 400.exception.ts
│ │ ├── 401.exception.ts
│ │ ├── 403.exception.ts
│ │ ├── 404.exception.ts
│ │ ├── 500.exception.ts
│ │ └── index.ts
│ ├── main.ts
│ ├── railway.json
│ ├── utils/
│ │ ├── advancedOperatorsSearch.ts
│ │ ├── createJid.ts
│ │ ├── errorResponse.ts
│ │ ├── fetchLatestWaWebVersion.ts
│ │ ├── findBotByTrigger.ts
│ │ ├── getConversationMessage.ts
│ │ ├── i18n.ts
│ │ ├── instrumentSentry.ts
│ │ ├── makeProxyAgent.ts
│ │ ├── onWhatsappCache.ts
│ │ ├── renderStatus.ts
│ │ ├── sendTelemetry.ts
│ │ ├── server-up.ts
│ │ ├── translations/
│ │ │ ├── en.json
│ │ │ ├── es.json
│ │ │ └── pt-BR.json
│ │ ├── use-multi-file-auth-state-prisma.ts
│ │ ├── use-multi-file-auth-state-provider-files.ts
│ │ └── use-multi-file-auth-state-redis-db.ts
│ └── validate/
│ ├── business.schema.ts
│ ├── chat.schema.ts
│ ├── group.schema.ts
│ ├── instance.schema.ts
│ ├── label.schema.ts
│ ├── message.schema.ts
│ ├── proxy.schema.ts
│ ├── settings.schema.ts
│ ├── template.schema.ts
│ ├── templateDelete.schema.ts
│ ├── templateEdit.schema.ts
│ └── validate.schema.ts
├── tsconfig.json
└── tsup.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .cursor/rules/README.md
================================================
# Evolution API Cursor Rules
Este diretório contém as regras e configurações do Cursor IDE para o projeto Evolution API.
## Estrutura dos Arquivos
### Arquivos Principais (alwaysApply: true)
- **`core-development.mdc`** - Princípios fundamentais de desenvolvimento
- **`project-context.mdc`** - Contexto específico do projeto Evolution API
- **`cursor.json`** - Configurações do Cursor IDE
### Regras Especializadas (alwaysApply: false)
Estas regras são ativadas automaticamente quando você trabalha nos arquivos correspondentes:
#### Camadas da Aplicação
- **`specialized-rules/service-rules.mdc`** - Padrões para services (`src/api/services/`)
- **`specialized-rules/controller-rules.mdc`** - Padrões para controllers (`src/api/controllers/`)
- **`specialized-rules/dto-rules.mdc`** - Padrões para DTOs (`src/api/dto/`)
- **`specialized-rules/guard-rules.mdc`** - Padrões para guards (`src/api/guards/`)
- **`specialized-rules/route-rules.mdc`** - Padrões para routers (`src/api/routes/`)
#### Tipos e Validação
- **`specialized-rules/type-rules.mdc`** - Definições TypeScript (`src/api/types/`)
- **`specialized-rules/validate-rules.mdc`** - Schemas de validação (`src/validate/`)
#### Utilitários
- **`specialized-rules/util-rules.mdc`** - Funções utilitárias (`src/utils/`)
#### Integrações
- **`specialized-rules/integration-channel-rules.mdc`** - Integrações de canal (`src/api/integrations/channel/`)
- **`specialized-rules/integration-chatbot-rules.mdc`** - Integrações de chatbot (`src/api/integrations/chatbot/`)
- **`specialized-rules/integration-storage-rules.mdc`** - Integrações de storage (`src/api/integrations/storage/`)
- **`specialized-rules/integration-event-rules.mdc`** - Integrações de eventos (`src/api/integrations/event/`)
## Como Usar
### Referências Cruzadas
Os arquivos principais fazem referência aos especializados usando a sintaxe `@specialized-rules/nome-do-arquivo.mdc`. Quando você trabalha em um arquivo específico, o Cursor automaticamente carrega as regras relevantes.
### Exemplo de Uso
Quando você edita um arquivo em `src/api/services/`, o Cursor automaticamente:
1. Carrega `core-development.mdc` (sempre ativo)
2. Carrega `project-context.mdc` (sempre ativo)
3. Carrega `specialized-rules/service-rules.mdc` (ativado pelo glob pattern)
### Padrões de Código
Cada arquivo de regras contém:
- **Estruturas padrão** - Como organizar o código
- **Padrões de nomenclatura** - Convenções de nomes
- **Exemplos práticos** - Código de exemplo
- **Anti-padrões** - O que evitar
- **Testes** - Como testar o código
- **Padrões de Commit** - Conventional Commits com commitlint
## Configuração do Cursor
O arquivo `cursor.json` contém:
- Configurações de formatação
- Padrões de código específicos do Evolution API
- Diretórios principais do projeto
- Integrações e tecnologias utilizadas
## Manutenção
Para manter as regras atualizadas:
1. Analise novos padrões no código
2. Atualize as regras especializadas correspondentes
3. Mantenha os exemplos sincronizados com o código real
4. Documente mudanças significativas
## Tecnologias Cobertas
- **Backend**: Node.js 20+ + TypeScript 5+ + Express.js
- **Database**: Prisma ORM (PostgreSQL/MySQL)
- **Cache**: Redis + Node-cache
- **Queue**: RabbitMQ + Amazon SQS
- **Real-time**: Socket.io
- **Storage**: AWS S3 + Minio
- **Validation**: JSONSchema7
- **Logging**: Pino
- **WhatsApp**: Baileys + Meta Business API
- **Integrations**: Chatwoot, Typebot, OpenAI, Dify
## Estrutura do Projeto
```
src/
├── api/
│ ├── controllers/ # Controllers (HTTP handlers)
│ ├── services/ # Business logic
│ ├── dto/ # Data Transfer Objects
│ ├── guards/ # Authentication/Authorization
│ ├── routes/ # Express routers
│ ├── types/ # TypeScript definitions
│ └── integrations/ # External integrations
│ ├── channel/ # WhatsApp channels (Baileys, Business API)
│ ├── chatbot/ # Chatbot integrations
│ ├── event/ # Event integrations
│ └── storage/ # Storage integrations
├── cache/ # Cache implementations
├── config/ # Configuration files
├── utils/ # Utility functions
├── validate/ # Validation schemas
└── exceptions/ # Custom exceptions
```
Este sistema de regras garante consistência no código e facilita o desenvolvimento seguindo os padrões estabelecidos do Evolution API.
================================================
FILE: .cursor/rules/core-development.mdc
================================================
---
description: Core development principles and standards for Evolution API development
globs:
alwaysApply: true
---
# Evolution API Development Standards
## Cross-References
- **Project Context**: @project-context.mdc for Evolution API-specific patterns
- **Specialized Rules**:
- @specialized-rules/service-rules.mdc for service layer patterns
- @specialized-rules/controller-rules.mdc for controller patterns
- @specialized-rules/dto-rules.mdc for DTO validation patterns
- @specialized-rules/guard-rules.mdc for authentication/authorization
- @specialized-rules/route-rules.mdc for router patterns
- @specialized-rules/type-rules.mdc for TypeScript definitions
- @specialized-rules/util-rules.mdc for utility functions
- @specialized-rules/validate-rules.mdc for validation schemas
- @specialized-rules/integration-channel-rules.mdc for channel integrations
- @specialized-rules/integration-chatbot-rules.mdc for chatbot integrations
- @specialized-rules/integration-storage-rules.mdc for storage integrations
- @specialized-rules/integration-event-rules.mdc for event integrations
- **TypeScript/Node.js**: Node.js 20+ + TypeScript 5+ best practices
- **Express/Prisma**: Express.js + Prisma ORM patterns
- **WhatsApp Integrations**: Baileys + Meta Business API patterns
## Senior Engineer Context - Evolution API Platform
- You are a senior software engineer working on a WhatsApp API platform
- Focus on Node.js + TypeScript + Express.js full-stack development
- Specialized in real-time messaging, WhatsApp integrations, and event-driven architecture
- Apply scalable patterns for multi-tenant API platform
- Consider WhatsApp integration workflow implications and performance at scale
## Fundamental Principles
### Code Quality Standards
- **Simplicity First**: Always prefer simple solutions over complex ones
- **DRY Principle**: Avoid code duplication - check for existing similar functionality before implementing
- **Single Responsibility**: Each function/class should have one clear purpose
- **Readable Code**: Write code that tells a story - clear naming and structure
### Problem Resolution Approach
- **Follow Existing Patterns**: Use established Service patterns, DTOs, and Integration patterns
- **Event-Driven First**: Leverage EventEmitter2 for event publishing when adding new features
- **Integration Pattern**: Follow existing WhatsApp integration patterns for new channels
- **Conservative Changes**: Prefer extending existing services over creating new architecture
- **Clean Migration**: Remove deprecated patterns when introducing new ones
- **Incremental Changes**: Break large changes into smaller, testable increments with proper migrations
### File and Function Organization - Node.js/TypeScript Structure
- **Services**: Keep services focused and under 200 lines
- **Controllers**: Keep controllers thin - only routing and validation
- **DTOs**: Use JSONSchema7 for all input validation
- **Integrations**: Follow `src/api/integrations/` structure for new integrations
- **Utils**: Extract common functionality into well-named utilities
- **Types**: Define clear TypeScript interfaces and types
### Code Analysis and Reflection
- After writing code, deeply reflect on scalability and maintainability
- Provide 1-2 paragraph analysis of code changes
- Suggest improvements or next steps based on reflection
- Consider performance, security, and maintenance implications
## Development Standards
### TypeScript Standards
- **Strict Mode**: Always use TypeScript strict mode
- **No Any**: Avoid `any` type - use proper typing
- **Interfaces**: Define clear contracts with interfaces
- **Enums**: Use enums for constants and status values
- **Generics**: Use generics for reusable components
### Error Handling Standards
- **HTTP Exceptions**: Use appropriate HTTP status codes
- **Logging**: Structured logging with context
- **Retry Logic**: Implement retry for external services
- **Graceful Degradation**: Handle service failures gracefully
### Security Standards
- **Input Validation**: Validate all inputs with JSONSchema7
- **Authentication**: Use API keys and JWT tokens
- **Rate Limiting**: Implement rate limiting for APIs
- **Data Sanitization**: Sanitize sensitive data in logs
### Performance Standards
- **Caching**: Use Redis for frequently accessed data
- **Database**: Optimize Prisma queries with proper indexing
- **Memory**: Monitor memory usage and implement cleanup
- **Async**: Use async/await properly with error handling
## Communication Standards
### Language Requirements
- **User Communication**: Always respond in Portuguese (PT-BR)
- **Code Comments**: English for technical documentation
- **API Documentation**: English for consistency
- **Error Messages**: Portuguese for user-facing errors
### Documentation Standards
- **Code Comments**: Document complex business logic
- **API Documentation**: Document all public endpoints
- **README**: Keep project documentation updated
- **Changelog**: Document breaking changes
## Quality Assurance
### Testing Standards
- **Unit Tests**: Test business logic in services
- **Integration Tests**: Test API endpoints
- **Mocks**: Mock external dependencies
- **Coverage**: Aim for 70%+ test coverage
### Code Review Standards
- **Peer Review**: All code must be reviewed
- **Automated Checks**: ESLint, Prettier, TypeScript
- **Security Review**: Check for security vulnerabilities
- **Performance Review**: Check for performance issues
### Commit Standards (Conventional Commits)
- **Format**: `type(scope): subject` (max 100 characters)
- **Types**:
- `feat` - New feature
- `fix` - Bug fix
- `docs` - Documentation changes
- `style` - Code style changes (formatting, etc)
- `refactor` - Code refactoring
- `perf` - Performance improvements
- `test` - Adding or updating tests
- `chore` - Maintenance tasks
- `ci` - CI/CD changes
- `build` - Build system changes
- `revert` - Reverting changes
- `security` - Security fixes
- **Examples**:
- `feat(api): add WhatsApp message status endpoint`
- `fix(baileys): resolve connection timeout issue`
- `docs(readme): update installation instructions`
- `refactor(service): extract common message validation logic`
- **Tools**: Use `npm run commit` (Commitizen) for guided commits
- **Validation**: Enforced by commitlint on commit-msg hook
## Evolution API Specific Patterns
### WhatsApp Integration Patterns
- **Connection Management**: One connection per instance
- **Event Handling**: Proper event listeners for Baileys
- **Message Processing**: Queue-based message processing
- **Error Recovery**: Automatic reconnection logic
### Multi-Database Support
- **Schema Compatibility**: Support PostgreSQL and MySQL
- **Migration Sync**: Keep migrations synchronized
- **Type Safety**: Use Prisma generated types
- **Connection Pooling**: Proper database connection management
### Cache Strategy
- **Redis Primary**: Use Redis for distributed caching
- **Local Fallback**: Node-cache for local fallback
- **TTL Strategy**: Appropriate TTL for different data types
- **Cache Invalidation**: Proper cache invalidation patterns
### Event System
- **EventEmitter2**: Use for internal events
- **WebSocket**: Socket.io for real-time updates
- **Queue Systems**: RabbitMQ/SQS for async processing
- **Webhook Processing**: Proper webhook validation and processing
================================================
FILE: .cursor/rules/cursor.json
================================================
{
"version": "1.0",
"description": "Cursor IDE configuration for Evolution API project",
"rules": {
"general": {
"max_line_length": 120,
"indent_size": 2,
"end_of_line": "lf",
"charset": "utf-8",
"trim_trailing_whitespace": true,
"insert_final_newline": true
},
"typescript": {
"quotes": "single",
"semi": true,
"trailing_comma": "es5",
"bracket_spacing": true,
"arrow_parens": "avoid",
"print_width": 120,
"tab_width": 2,
"use_tabs": false,
"single_quote": true,
"end_of_line": "lf",
"strict": true,
"no_implicit_any": true,
"strict_null_checks": true
},
"javascript": {
"quotes": "single",
"semi": true,
"trailing_comma": "es5",
"bracket_spacing": true,
"arrow_parens": "avoid",
"print_width": 120,
"tab_width": 2,
"use_tabs": false,
"single_quote": true,
"end_of_line": "lf",
"style_guide": "eslint-airbnb"
},
"json": {
"tab_width": 2,
"use_tabs": false,
"parser": "json"
},
"ignore": {
"files": [
"node_modules/**",
"dist/**",
"build/**",
".git/**",
"*.min.js",
"*.min.css",
".env",
".env.*",
".env.example",
"coverage/**",
"*.log",
"*.lock",
"pnpm-lock.yaml",
"package-lock.json",
"yarn.lock",
"log/**",
"tmp/**",
"instances/**",
"public/uploads/**",
"*.dump",
"*.rdb",
"*.mmdb",
".DS_Store",
"*.swp",
"*.swo",
"*.un~",
".jest-cache",
".idea/**",
".vscode/**",
".yalc/**",
"yalc.lock",
"*.local",
"prisma/migrations/**",
"prisma/mysql-migrations/**",
"prisma/postgresql-migrations/**"
]
},
"search": {
"exclude_patterns": [
"**/node_modules/**",
"**/dist/**",
"**/build/**",
"**/.git/**",
"**/coverage/**",
"**/log/**",
"**/tmp/**",
"**/instances/**",
"**/public/uploads/**",
"**/*.min.js",
"**/*.min.css",
"**/*.log",
"**/*.lock",
"**/pnpm-lock.yaml",
"**/package-lock.json",
"**/yarn.lock",
"**/*.dump",
"**/*.rdb",
"**/*.mmdb",
"**/.DS_Store",
"**/*.swp",
"**/*.swo",
"**/*.un~",
"**/.jest-cache",
"**/.idea/**",
"**/.vscode/**",
"**/.yalc/**",
"**/yalc.lock",
"**/*.local",
"**/prisma/migrations/**",
"**/prisma/mysql-migrations/**",
"**/prisma/postgresql-migrations/**"
]
},
"evolution_api": {
"project_type": "nodejs_typescript_api",
"backend_framework": "express_prisma",
"database": ["postgresql", "mysql"],
"cache": ["redis", "node_cache"],
"queue": ["rabbitmq", "sqs"],
"real_time": "socket_io",
"file_storage": ["aws_s3", "minio"],
"validation": "class_validator",
"logging": "pino",
"main_directories": {
"source": "src/",
"api": "src/api/",
"controllers": "src/api/controllers/",
"services": "src/api/services/",
"integrations": "src/api/integrations/",
"dto": "src/api/dto/",
"types": "src/api/types/",
"guards": "src/api/guards/",
"routes": "src/api/routes/",
"cache": "src/cache/",
"config": "src/config/",
"utils": "src/utils/",
"exceptions": "src/exceptions/",
"validate": "src/validate/",
"prisma": "prisma/",
"tests": "test/",
"docs": "docs/"
},
"key_patterns": [
"whatsapp_integration",
"multi_database_support",
"instance_management",
"event_driven_architecture",
"service_layer_pattern",
"dto_validation",
"webhook_processing",
"message_queuing",
"real_time_communication",
"file_storage_integration"
],
"whatsapp_integrations": [
"baileys",
"meta_business_api",
"whatsapp_cloud_api"
],
"external_integrations": [
"chatwoot",
"typebot",
"openai",
"dify",
"rabbitmq",
"sqs",
"s3",
"minio"
]
}
}
}
================================================
FILE: .cursor/rules/project-context.mdc
================================================
---
description: Evolution API project-specific context and constraints
globs:
alwaysApply: true
---
# Evolution API Project Context
## Cross-References
- **Core Development**: @core-development.mdc for fundamental development principles
- **Specialized Rules**: Reference specific specialized rules when working on:
- Services: @specialized-rules/service-rules.mdc
- Controllers: @specialized-rules/controller-rules.mdc
- DTOs: @specialized-rules/dto-rules.mdc
- Guards: @specialized-rules/guard-rules.mdc
- Routes: @specialized-rules/route-rules.mdc
- Types: @specialized-rules/type-rules.mdc
- Utils: @specialized-rules/util-rules.mdc
- Validation: @specialized-rules/validate-rules.mdc
- Channel Integrations: @specialized-rules/integration-channel-rules.mdc
- Chatbot Integrations: @specialized-rules/integration-chatbot-rules.mdc
- Storage Integrations: @specialized-rules/integration-storage-rules.mdc
- Event Integrations: @specialized-rules/integration-event-rules.mdc
- **TypeScript/Node.js**: Node.js 20+ + TypeScript 5+ backend standards
- **Express/Prisma**: Express.js + Prisma ORM patterns
- **WhatsApp Integrations**: Baileys, Meta Business API, and other messaging platforms
## Technology Stack
- **Backend**: Node.js 20+ + TypeScript 5+ + Express.js
- **Database**: Prisma ORM (PostgreSQL/MySQL support)
- **Cache**: Redis + Node-cache for local fallback
- **Queue**: RabbitMQ + Amazon SQS for message processing
- **Real-time**: Socket.io for WebSocket connections
- **Storage**: AWS S3 + Minio for file storage
- **Validation**: JSONSchema7 for input validation
- **Logging**: Pino for structured logging
- **Architecture**: Multi-tenant API with WhatsApp integrations
## Project-Specific Patterns
### WhatsApp Integration Architecture
- **MANDATORY**: All WhatsApp integrations must follow established patterns
- **BAILEYS**: Use `whatsapp.baileys.service.ts` patterns for WhatsApp Web
- **META BUSINESS**: Use `whatsapp.business.service.ts` for official API
- **CONNECTION MANAGEMENT**: One connection per instance with proper lifecycle
- **EVENT HANDLING**: Proper event listeners and error handling
### Multi-Database Architecture
- **CRITICAL**: Support both PostgreSQL and MySQL
- **SCHEMAS**: Use appropriate schema files (postgresql-schema.prisma / mysql-schema.prisma)
- **MIGRATIONS**: Keep migrations synchronized between databases
- **TYPES**: Use database-specific types (@db.JsonB vs @db.Json)
- **COMPATIBILITY**: Ensure feature parity between databases
### API Integration Workflow
- **CORE FEATURE**: REST API for WhatsApp communication
- **COMPLEXITY**: High - involves webhook processing, message routing, and instance management
- **COMPONENTS**: Instance management, message handling, media processing
- **INTEGRATIONS**: Baileys, Meta Business API, Chatwoot, Typebot, OpenAI, Dify
### Multi-Tenant Instance Architecture
- **CRITICAL**: All operations must be scoped by instance
- **ISOLATION**: Complete data isolation between instances
- **SECURITY**: Validate instance ownership before operations
- **SCALING**: Support thousands of concurrent instances
- **AUTHENTICATION**: API key-based authentication per instance
## Documentation Requirements
### Implementation Documentation
- **MANDATORY**: Document complex integration patterns
- **LOCATION**: Use inline comments for business logic
- **API DOCS**: Document all public endpoints
- **WEBHOOK DOCS**: Document webhook payloads and signatures
### Change Documentation
- **CHANGELOG**: Document breaking changes
- **MIGRATION GUIDES**: Document database migrations
- **INTEGRATION GUIDES**: Document new integration patterns
## Environment and Security
### Environment Variables
- **CRITICAL**: Never hardcode sensitive values
- **VALIDATION**: Validate required environment variables on startup
- **SECURITY**: Use secure defaults and proper encryption
- **DOCUMENTATION**: Document all environment variables
### File Organization - Node.js/TypeScript Structure
- **CONTROLLERS**: Organized by feature (`api/controllers/`)
- **SERVICES**: Business logic in service classes (`api/services/`)
- **INTEGRATIONS**: External integrations (`api/integrations/`)
- **DTOS**: Data transfer objects (`api/dto/`)
- **TYPES**: TypeScript types (`api/types/`)
- **UTILS**: Utility functions (`utils/`)
## Integration Points
### WhatsApp Providers
- **BAILEYS**: WhatsApp Web integration with QR code
- **META BUSINESS**: Official WhatsApp Business API
- **CLOUD API**: WhatsApp Cloud API integration
- **WEBHOOK PROCESSING**: Proper webhook validation and processing
### External Integrations
- **CHATWOOT**: Customer support platform integration
- **TYPEBOT**: Chatbot flow integration
- **OPENAI**: AI-powered chat integration
- **DIFY**: AI workflow integration
- **STORAGE**: S3/Minio for media file storage
### Event-Driven Communication
- **EVENTEMITTER2**: Internal event system
- **SOCKET.IO**: Real-time WebSocket communication
- **RABBITMQ**: Message queue for async processing
- **SQS**: Amazon SQS for cloud-based queuing
- **WEBHOOKS**: Outbound webhook system
## Development Constraints
### Language Requirements
- **USER COMMUNICATION**: Always respond in Portuguese (PT-BR)
- **CODE/COMMENTS**: English for code and technical documentation
- **API RESPONSES**: English for consistency
- **ERROR MESSAGES**: Portuguese for user-facing errors
### Performance Constraints
- **MEMORY**: Efficient memory usage for multiple instances
- **DATABASE**: Optimized queries with proper indexing
- **CACHE**: Strategic caching for frequently accessed data
- **CONNECTIONS**: Proper connection pooling and management
### Security Constraints
- **AUTHENTICATION**: API key validation for all endpoints
- **AUTHORIZATION**: Instance-based access control
- **INPUT VALIDATION**: Validate all inputs with JSONSchema7
- **RATE LIMITING**: Prevent abuse with rate limiting
- **WEBHOOK SECURITY**: Validate webhook signatures
## Quality Standards
- **TYPE SAFETY**: Full TypeScript coverage with strict mode
- **ERROR HANDLING**: Comprehensive error scenarios with proper logging
- **TESTING**: Unit and integration tests for critical paths
- **MONITORING**: Proper logging and error tracking
- **DOCUMENTATION**: Clear API documentation and code comments
- **PERFORMANCE**: Optimized for high-throughput message processing
- **SECURITY**: Secure by default with proper validation
- **SCALABILITY**: Design for horizontal scaling
## Evolution API Specific Development Patterns
### Instance Management
- **LIFECYCLE**: Proper instance creation, connection, and cleanup
- **STATE MANAGEMENT**: Track connection status and health
- **RECOVERY**: Automatic reconnection and error recovery
- **MONITORING**: Health checks and status reporting
### Message Processing
- **QUEUE-BASED**: Use queues for message processing
- **RETRY LOGIC**: Implement exponential backoff for failures
- **MEDIA HANDLING**: Proper media upload and processing
- **WEBHOOK DELIVERY**: Reliable webhook delivery with retries
### Integration Patterns
- **SERVICE LAYER**: Business logic in service classes
- **DTO VALIDATION**: Input validation with JSONSchema7
- **ERROR HANDLING**: Consistent error responses
- **LOGGING**: Structured logging with correlation IDs
### Database Patterns
- **PRISMA**: Use Prisma ORM for all database operations
- **TRANSACTIONS**: Use transactions for multi-step operations
- **MIGRATIONS**: Proper migration management
- **INDEXING**: Optimize queries with appropriate indexes
================================================
FILE: .cursor/rules/specialized-rules/controller-rules.mdc
================================================
---
description: Controller patterns for Evolution API
globs:
- "src/api/controllers/**/*.ts"
- "src/api/integrations/**/controllers/*.ts"
alwaysApply: false
---
# Evolution API Controller Rules
## Controller Structure Pattern
### Standard Controller Class
```typescript
export class ExampleController {
constructor(private readonly exampleService: ExampleService) {}
public async createExample(instance: InstanceDto, data: ExampleDto) {
return this.exampleService.create(instance, data);
}
public async findExample(instance: InstanceDto) {
return this.exampleService.find(instance);
}
}
```
## Dependency Injection Pattern
### Service Injection
```typescript
// CORRECT - Evolution API pattern
export class ChatController {
constructor(private readonly waMonitor: WAMonitoringService) {}
public async whatsappNumber({ instanceName }: InstanceDto, data: WhatsAppNumberDto) {
return await this.waMonitor.waInstances[instanceName].getWhatsAppNumbers(data);
}
}
// INCORRECT - Don't inject multiple services when waMonitor is sufficient
export class ChatController {
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly prismaRepository: PrismaRepository, // ❌ Unnecessary if waMonitor has access
private readonly configService: ConfigService, // ❌ Unnecessary if waMonitor has access
) {}
}
```
## Method Signature Pattern
### Instance Parameter Pattern
```typescript
// CORRECT - Evolution API pattern (destructuring instanceName)
public async fetchCatalog({ instanceName }: InstanceDto, data: getCatalogDto) {
return await this.waMonitor.waInstances[instanceName].fetchCatalog(instanceName, data);
}
// CORRECT - Alternative pattern for full instance (when using services)
public async createTemplate(instance: InstanceDto, data: TemplateDto) {
return this.templateService.create(instance, data);
}
// INCORRECT - Don't use generic method names
public async methodName(instance: InstanceDto, data: DataDto) { // ❌ Use specific names
return this.service.performAction(instance, data);
}
```
## WAMonitor Access Pattern
### Direct WAMonitor Usage
```typescript
// CORRECT - Standard pattern in controllers
export class CallController {
constructor(private readonly waMonitor: WAMonitoringService) {}
public async offerCall({ instanceName }: InstanceDto, data: OfferCallDto) {
return await this.waMonitor.waInstances[instanceName].offerCall(data);
}
}
```
## Controller Registration Pattern
### Server Module Registration
```typescript
// In server.module.ts
export const templateController = new TemplateController(templateService);
export const businessController = new BusinessController(waMonitor);
export const chatController = new ChatController(waMonitor);
export const callController = new CallController(waMonitor);
```
## Error Handling in Controllers
### Let Services Handle Errors
```typescript
// CORRECT - Let service handle errors
public async fetchCatalog(instance: InstanceDto, data: getCatalogDto) {
return await this.waMonitor.waInstances[instance.instanceName].fetchCatalog(instance.instanceName, data);
}
// INCORRECT - Don't add try-catch in controllers unless specific handling needed
public async fetchCatalog(instance: InstanceDto, data: getCatalogDto) {
try {
return await this.waMonitor.waInstances[instance.instanceName].fetchCatalog(instance.instanceName, data);
} catch (error) {
throw error; // ❌ Unnecessary try-catch
}
}
```
## Complex Controller Pattern
### Instance Controller Pattern
```typescript
export class InstanceController {
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly configService: ConfigService,
private readonly prismaRepository: PrismaRepository,
private readonly eventEmitter: EventEmitter2,
private readonly chatwootService: ChatwootService,
private readonly settingsService: SettingsService,
private readonly proxyService: ProxyController,
private readonly cache: CacheService,
private readonly chatwootCache: CacheService,
private readonly baileysCache: CacheService,
private readonly providerFiles: ProviderFiles,
) {}
private readonly logger = new Logger('InstanceController');
// Multiple methods handling different aspects
public async createInstance(data: InstanceDto) {
// Complex instance creation logic
}
public async deleteInstance({ instanceName }: InstanceDto) {
// Complex instance deletion logic
}
}
```
## Channel Controller Pattern
### Base Channel Controller
```typescript
export class ChannelController {
public prismaRepository: PrismaRepository;
public waMonitor: WAMonitoringService;
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
this.prisma = prismaRepository;
this.monitor = waMonitor;
}
// Getters and setters for dependency access
public set prisma(prisma: PrismaRepository) {
this.prismaRepository = prisma;
}
public get prisma() {
return this.prismaRepository;
}
public set monitor(waMonitor: WAMonitoringService) {
this.waMonitor = waMonitor;
}
public get monitor() {
return this.waMonitor;
}
}
```
### Extended Channel Controller
```typescript
export class EvolutionController extends ChannelController implements ChannelControllerInterface {
private readonly logger = new Logger('EvolutionController');
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
super(prismaRepository, waMonitor);
}
integrationEnabled: boolean;
public async receiveWebhook(data: any) {
const numberId = data.numberId;
if (!numberId) {
this.logger.error('WebhookService -> receiveWebhookEvolution -> numberId not found');
return;
}
const instance = await this.prismaRepository.instance.findFirst({
where: { number: numberId },
});
if (!instance) {
this.logger.error('WebhookService -> receiveWebhook -> instance not found');
return;
}
await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data);
return {
status: 'success',
};
}
}
```
## Chatbot Controller Pattern
### Base Chatbot Controller
```typescript
export abstract class BaseChatbotController<BotType = any, BotData extends BaseChatbotDto = BaseChatbotDto>
extends ChatbotController
implements ChatbotControllerInterface
{
public readonly logger: Logger;
integrationEnabled: boolean;
// Abstract methods to be implemented
protected abstract readonly integrationName: string;
protected abstract processBot(/* parameters */): Promise<void>;
protected abstract getFallbackBotId(settings: any): string | undefined;
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
super(prismaRepository, waMonitor);
}
// Base implementation methods
public async createBot(instance: InstanceDto, data: BotData) {
// Common bot creation logic
}
}
```
## Method Naming Conventions
### Standard Method Names
- `create*()` - Create operations
- `find*()` - Find operations
- `fetch*()` - Fetch from external APIs
- `send*()` - Send operations
- `receive*()` - Receive webhook/data
- `handle*()` - Handle specific actions
- `offer*()` - Offer services (like calls)
## Return Patterns
### Direct Return Pattern
```typescript
// CORRECT - Direct return from service
public async createTemplate(instance: InstanceDto, data: TemplateDto) {
return this.templateService.create(instance, data);
}
// CORRECT - Direct return from waMonitor
public async offerCall({ instanceName }: InstanceDto, data: OfferCallDto) {
return await this.waMonitor.waInstances[instanceName].offerCall(data);
}
```
## Controller Testing Pattern
### Unit Test Structure
```typescript
describe('ExampleController', () => {
let controller: ExampleController;
let service: jest.Mocked<ExampleService>;
beforeEach(() => {
const mockService = {
create: jest.fn(),
find: jest.fn(),
};
controller = new ExampleController(mockService as any);
service = mockService as any;
});
describe('createExample', () => {
it('should call service create method', async () => {
const instance = { instanceName: 'test' };
const data = { test: 'data' };
const expectedResult = { success: true };
service.create.mockResolvedValue(expectedResult);
const result = await controller.createExample(instance, data);
expect(service.create).toHaveBeenCalledWith(instance, data);
expect(result).toEqual(expectedResult);
});
});
});
```
## Interface Implementation
### Controller Interface Pattern
```typescript
export interface ChannelControllerInterface {
integrationEnabled: boolean;
}
export interface ChatbotControllerInterface {
integrationEnabled: boolean;
createBot(instance: InstanceDto, data: any): Promise<any>;
findBot(instance: InstanceDto): Promise<any>;
// ... other methods
}
```
## Controller Organization
### File Naming Convention
- `*.controller.ts` - Main controllers
- `*/*.controller.ts` - Integration-specific controllers
### Method Organization
1. Constructor
2. Public methods (alphabetical order)
3. Private methods (if any)
### Import Organization
```typescript
// DTOs first
import { InstanceDto } from '@api/dto/instance.dto';
import { ExampleDto } from '@api/dto/example.dto';
// Services
import { ExampleService } from '@api/services/example.service';
// Types
import { WAMonitoringService } from '@api/services/monitor.service';
```
================================================
FILE: .cursor/rules/specialized-rules/dto-rules.mdc
================================================
---
description: DTO patterns and validation for Evolution API
globs:
- "src/api/dto/**/*.ts"
- "src/api/integrations/**/dto/*.ts"
alwaysApply: false
---
# Evolution API DTO Rules
## DTO Structure Pattern
### Basic DTO Class
```typescript
export class ExampleDto {
name: string;
category: string;
allowCategoryChange: boolean;
language: string;
components: any;
webhookUrl?: string;
}
```
## Inheritance Pattern
### DTO Inheritance
```typescript
// CORRECT - Evolution API pattern
export class InstanceDto extends IntegrationDto {
instanceName: string;
instanceId?: string;
qrcode?: boolean;
businessId?: string;
number?: string;
integration?: string;
token?: string;
status?: string;
ownerJid?: string;
profileName?: string;
profilePicUrl?: string;
// Settings
rejectCall?: boolean;
msgCall?: string;
groupsIgnore?: boolean;
alwaysOnline?: boolean;
readMessages?: boolean;
readStatus?: boolean;
syncFullHistory?: boolean;
wavoipToken?: string;
// Proxy settings
proxyHost?: string;
proxyPort?: string;
proxyProtocol?: string;
proxyUsername?: string;
proxyPassword?: string;
// Webhook configuration
webhook?: {
enabled?: boolean;
events?: string[];
headers?: JsonValue;
url?: string;
byEvents?: boolean;
base64?: boolean;
};
// Chatwoot integration
chatwootAccountId?: string;
chatwootConversationPending?: boolean;
chatwootAutoCreate?: boolean;
chatwootDaysLimitImportMessages?: number;
chatwootImportContacts?: boolean;
chatwootImportMessages?: boolean;
chatwootLogo?: string;
chatwootMergeBrazilContacts?: boolean;
chatwootNameInbox?: string;
chatwootOrganization?: string;
chatwootReopenConversation?: boolean;
chatwootSignMsg?: boolean;
chatwootToken?: string;
chatwootUrl?: string;
}
```
## Base DTO Pattern
### Base Chatbot DTO
```typescript
/**
* Base DTO for all chatbot integrations
* Contains common properties shared by all chatbot types
*/
export class BaseChatbotDto {
enabled?: boolean;
description: string;
expire?: number;
keywordFinish?: string;
delayMessage?: number;
unknownMessage?: string;
listeningFromMe?: boolean;
stopBotFromMe?: boolean;
keepOpen?: boolean;
debounceTime?: number;
triggerType: TriggerType;
triggerOperator?: TriggerOperator;
triggerValue?: string;
ignoreJids?: string[];
splitMessages?: boolean;
timePerChar?: number;
}
/**
* Base settings DTO for all chatbot integrations
*/
export class BaseChatbotSettingDto {
expire?: number;
keywordFinish?: string;
delayMessage?: number;
unknownMessage?: string;
listeningFromMe?: boolean;
stopBotFromMe?: boolean;
keepOpen?: boolean;
debounceTime?: number;
ignoreJids?: string[];
splitMessages?: boolean;
timePerChar?: number;
}
```
## Message DTO Patterns
### Send Message DTOs
```typescript
export class Metadata {
number: string;
delay?: number;
}
export class SendTextDto extends Metadata {
text: string;
linkPreview?: boolean;
mentionsEveryOne?: boolean;
mentioned?: string[];
}
export class SendListDto extends Metadata {
title: string;
description: string;
buttonText: string;
footerText?: string;
sections: Section[];
}
export class ContactMessage {
fullName: string;
wuid: string;
phoneNumber: string;
organization?: string;
email?: string;
url?: string;
}
export class SendTemplateDto extends Metadata {
name: string;
language: string;
components: any;
}
```
## Simple DTO Patterns
### Basic DTOs
```typescript
export class NumberDto {
number: string;
}
export class LabelDto {
id?: string;
name: string;
color: string;
predefinedId?: string;
}
export class HandleLabelDto {
number: string;
labelId: string;
}
export class ProfileNameDto {
name: string;
}
export class WhatsAppNumberDto {
numbers: string[];
}
```
## Complex DTO Patterns
### Business DTOs
```typescript
export class getCatalogDto {
number?: string;
limit?: number;
cursor?: string;
}
export class getCollectionsDto {
number?: string;
limit?: number;
cursor?: string;
}
export class NumberBusiness {
number: string;
name?: string;
description?: string;
email?: string;
websites?: string[];
latitude?: number;
longitude?: number;
address?: string;
profilehandle?: string;
}
```
## Settings DTO Pattern
### Settings Configuration
```typescript
export class SettingsDto {
rejectCall?: boolean;
msgCall?: string;
groupsIgnore?: boolean;
alwaysOnline?: boolean;
readMessages?: boolean;
readStatus?: boolean;
syncFullHistory?: boolean;
wavoipToken?: string;
}
export class ProxyDto {
host?: string;
port?: string;
protocol?: string;
username?: string;
password?: string;
}
```
## Presence DTO Pattern
### WhatsApp Presence
```typescript
export class SetPresenceDto {
presence: WAPresence;
}
export class SendPresenceDto {
number: string;
presence: WAPresence;
}
```
## DTO Structure (No Decorators)
### Simple DTO Classes (Evolution API Pattern)
```typescript
// CORRECT - Evolution API pattern (no decorators)
export class ExampleDto {
name: string;
description?: string;
enabled: boolean;
items?: string[];
timeout?: number;
}
// INCORRECT - Don't use class-validator decorators
export class ValidatedDto {
@IsString() // ❌ Evolution API doesn't use decorators
name: string;
}
```
## Type Safety Patterns
### Prisma Type Integration
```typescript
import { JsonValue } from '@prisma/client/runtime/library';
import { WAPresence } from 'baileys';
import { TriggerOperator, TriggerType } from '@prisma/client';
export class TypeSafeDto {
presence: WAPresence;
triggerType: TriggerType;
triggerOperator?: TriggerOperator;
metadata?: JsonValue;
}
```
## DTO Documentation
### JSDoc Comments
```typescript
/**
* DTO for creating WhatsApp templates
* Used by Meta Business API integration
*/
export class TemplateDto {
/** Template name - must be unique */
name: string;
/** Template category (MARKETING, UTILITY, AUTHENTICATION) */
category: string;
/** Whether category can be changed after creation */
allowCategoryChange: boolean;
/** Language code (e.g., 'pt_BR', 'en_US') */
language: string;
/** Template components (header, body, footer, buttons) */
components: any;
/** Optional webhook URL for template status updates */
webhookUrl?: string;
}
```
## DTO Naming Conventions
### Standard Naming Patterns
- `*Dto` - Data transfer objects
- `Create*Dto` - Creation DTOs
- `Update*Dto` - Update DTOs
- `Send*Dto` - Message sending DTOs
- `Get*Dto` - Query DTOs
- `Handle*Dto` - Action DTOs
## File Organization
### DTO File Structure
```
src/api/dto/
├── instance.dto.ts # Main instance DTO
├── template.dto.ts # Template management
├── sendMessage.dto.ts # Message sending DTOs
├── chat.dto.ts # Chat operations
├── business.dto.ts # Business API DTOs
├── group.dto.ts # Group management
├── label.dto.ts # Label management
├── proxy.dto.ts # Proxy configuration
├── settings.dto.ts # Instance settings
└── call.dto.ts # Call operations
```
## Integration DTO Patterns
### Chatbot Integration DTOs
```typescript
// Base for all chatbot DTOs
export class BaseChatbotDto {
enabled?: boolean;
description: string;
// ... common properties
}
// Specific chatbot DTOs extend base
export class TypebotDto extends BaseChatbotDto {
url: string;
typebot: string;
// ... typebot-specific properties
}
export class OpenaiDto extends BaseChatbotDto {
apiKey: string;
model: string;
// ... openai-specific properties
}
```
## DTO Testing Pattern
### DTO Validation Tests
```typescript
describe('ExampleDto', () => {
it('should validate required fields', () => {
const dto = new ExampleDto();
dto.name = 'test';
dto.category = 'MARKETING';
dto.allowCategoryChange = true;
dto.language = 'pt_BR';
dto.components = {};
expect(dto.name).toBe('test');
expect(dto.category).toBe('MARKETING');
});
it('should handle optional fields', () => {
const dto = new ExampleDto();
dto.name = 'test';
dto.category = 'MARKETING';
dto.allowCategoryChange = true;
dto.language = 'pt_BR';
dto.components = {};
dto.webhookUrl = 'https://example.com/webhook';
expect(dto.webhookUrl).toBe('https://example.com/webhook');
});
});
```
## DTO Transformation
### Request to DTO Mapping (Evolution API Pattern)
```typescript
// CORRECT - Evolution API uses RouterBroker dataValidate
const response = await this.dataValidate<ExampleDto>({
request: req,
schema: exampleSchema, // JSONSchema7
ClassRef: ExampleDto,
execute: (instance, data) => controller.method(instance, data),
});
// INCORRECT - Don't use class-validator
const dto = plainToClass(ExampleDto, req.body); // ❌ Not used in Evolution API
const errors = await validate(dto); // ❌ Not used in Evolution API
```
================================================
FILE: .cursor/rules/specialized-rules/guard-rules.mdc
================================================
---
description: Guard patterns for authentication and authorization in Evolution API
globs:
- "src/api/guards/**/*.ts"
alwaysApply: false
---
# Evolution API Guard Rules
## Guard Structure Pattern
### Standard Guard Function
```typescript
import { NextFunction, Request, Response } from 'express';
import { Logger } from '@config/logger.config';
import { UnauthorizedException, ForbiddenException } from '@exceptions';
const logger = new Logger('GUARD');
async function guardFunction(req: Request, _: Response, next: NextFunction) {
// Guard logic here
if (validationFails) {
throw new UnauthorizedException();
}
return next();
}
export const guardName = { guardFunction };
```
## Authentication Guard Pattern
### API Key Authentication
```typescript
async function apikey(req: Request, _: Response, next: NextFunction) {
const env = configService.get<Auth>('AUTHENTICATION').API_KEY;
const key = req.get('apikey');
const db = configService.get<Database>('DATABASE');
if (!key) {
throw new UnauthorizedException();
}
// Global API key check
if (env.KEY === key) {
return next();
}
// Special routes handling
if ((req.originalUrl.includes('/instance/create') || req.originalUrl.includes('/instance/fetchInstances')) && !key) {
throw new ForbiddenException('Missing global api key', 'The global api key must be set');
}
const param = req.params as unknown as InstanceDto;
try {
if (param?.instanceName) {
const instance = await prismaRepository.instance.findUnique({
where: { name: param.instanceName },
});
if (instance.token === key) {
return next();
}
} else {
if (req.originalUrl.includes('/instance/fetchInstances') && db.SAVE_DATA.INSTANCE) {
const instanceByKey = await prismaRepository.instance.findFirst({
where: { token: key },
});
if (instanceByKey) {
return next();
}
}
}
} catch (error) {
logger.error(error);
}
throw new UnauthorizedException();
}
export const authGuard = { apikey };
```
## Instance Validation Guards
### Instance Exists Guard
```typescript
async function getInstance(instanceName: string) {
try {
const cacheConf = configService.get<CacheConf>('CACHE');
const exists = !!waMonitor.waInstances[instanceName];
if (cacheConf.REDIS.ENABLED && cacheConf.REDIS.SAVE_INSTANCES) {
const keyExists = await cache.has(instanceName);
return exists || keyExists;
}
return exists || (await prismaRepository.instance.findMany({ where: { name: instanceName } })).length > 0;
} catch (error) {
throw new InternalServerErrorException(error?.toString());
}
}
export async function instanceExistsGuard(req: Request, _: Response, next: NextFunction) {
if (req.originalUrl.includes('/instance/create')) {
return next();
}
const param = req.params as unknown as InstanceDto;
if (!param?.instanceName) {
throw new BadRequestException('"instanceName" not provided.');
}
if (!(await getInstance(param.instanceName))) {
throw new NotFoundException(`The "${param.instanceName}" instance does not exist`);
}
next();
}
```
### Instance Logged Guard
```typescript
export async function instanceLoggedGuard(req: Request, _: Response, next: NextFunction) {
if (req.originalUrl.includes('/instance/create')) {
const instance = req.body as InstanceDto;
if (await getInstance(instance.instanceName)) {
throw new ForbiddenException(`This name "${instance.instanceName}" is already in use.`);
}
if (waMonitor.waInstances[instance.instanceName]) {
delete waMonitor.waInstances[instance.instanceName];
}
}
next();
}
```
## Telemetry Guard Pattern
### Telemetry Collection
```typescript
class Telemetry {
public collectTelemetry(req: Request, res: Response, next: NextFunction): void {
// Collect telemetry data
const telemetryData = {
route: req.originalUrl,
method: req.method,
timestamp: new Date(),
userAgent: req.get('User-Agent'),
};
// Send telemetry asynchronously (don't block request)
setImmediate(() => {
this.sendTelemetry(telemetryData);
});
next();
}
private async sendTelemetry(data: any): Promise<void> {
try {
// Send telemetry data
} catch (error) {
// Silently fail - don't affect main request
}
}
}
export default Telemetry;
```
## Guard Composition Pattern
### Multiple Guards Usage
```typescript
// In router setup
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard['apikey']];
router
.use('/instance', new InstanceRouter(configService, ...guards).router)
.use('/message', new MessageRouter(...guards).router)
.use('/chat', new ChatRouter(...guards).router);
```
## Error Handling in Guards
### Proper Exception Throwing
```typescript
// CORRECT - Use proper HTTP exceptions
if (!apiKey) {
throw new UnauthorizedException('API key required');
}
if (instanceExists) {
throw new ForbiddenException('Instance already exists');
}
if (!instanceFound) {
throw new NotFoundException('Instance not found');
}
if (validationFails) {
throw new BadRequestException('Invalid request parameters');
}
// INCORRECT - Don't use generic Error
if (!apiKey) {
throw new Error('API key required'); // ❌ Use specific exceptions
}
```
## Configuration Access in Guards
### Config Service Usage
```typescript
async function configAwareGuard(req: Request, _: Response, next: NextFunction) {
const authConfig = configService.get<Auth>('AUTHENTICATION');
const cacheConfig = configService.get<CacheConf>('CACHE');
const dbConfig = configService.get<Database>('DATABASE');
// Use configuration for guard logic
if (authConfig.API_KEY.KEY === providedKey) {
return next();
}
throw new UnauthorizedException();
}
```
## Database Access in Guards
### Prisma Repository Usage
```typescript
async function databaseGuard(req: Request, _: Response, next: NextFunction) {
try {
const param = req.params as unknown as InstanceDto;
const instance = await prismaRepository.instance.findUnique({
where: { name: param.instanceName },
});
if (!instance) {
throw new NotFoundException('Instance not found');
}
// Additional validation logic
if (instance.status !== 'active') {
throw new ForbiddenException('Instance not active');
}
return next();
} catch (error) {
logger.error('Database guard error:', error);
throw new InternalServerErrorException('Database access failed');
}
}
```
## Cache Integration in Guards
### Cache Service Usage
```typescript
async function cacheAwareGuard(req: Request, _: Response, next: NextFunction) {
const cacheConf = configService.get<CacheConf>('CACHE');
if (cacheConf.REDIS.ENABLED) {
const cached = await cache.get(`guard:${req.params.instanceName}`);
if (cached) {
// Use cached validation result
return next();
}
}
// Perform validation and cache result
const isValid = await performValidation(req.params.instanceName);
if (cacheConf.REDIS.ENABLED) {
await cache.set(`guard:${req.params.instanceName}`, isValid, 300); // 5 min TTL
}
if (isValid) {
return next();
}
throw new UnauthorizedException();
}
```
## Logging in Guards
### Structured Logging
```typescript
const logger = new Logger('GUARD');
async function loggedGuard(req: Request, _: Response, next: NextFunction) {
logger.log(`Guard validation started for ${req.originalUrl}`);
try {
// Guard logic
const isValid = await validateRequest(req);
if (isValid) {
logger.log(`Guard validation successful for ${req.params.instanceName}`);
return next();
}
logger.warn(`Guard validation failed for ${req.params.instanceName}`);
throw new UnauthorizedException();
} catch (error) {
logger.error(`Guard validation error: ${error.message}`, error.stack);
throw error;
}
}
```
## Guard Testing Pattern
### Unit Test Structure
```typescript
describe('authGuard', () => {
let req: Partial<Request>;
let res: Partial<Response>;
let next: NextFunction;
beforeEach(() => {
req = {
get: jest.fn(),
params: {},
originalUrl: '/test',
};
res = {};
next = jest.fn();
});
describe('apikey', () => {
it('should pass with valid global API key', async () => {
(req.get as jest.Mock).mockReturnValue('valid-global-key');
await authGuard.apikey(req as Request, res as Response, next);
expect(next).toHaveBeenCalled();
});
it('should throw UnauthorizedException with no API key', async () => {
(req.get as jest.Mock).mockReturnValue(undefined);
await expect(
authGuard.apikey(req as Request, res as Response, next)
).rejects.toThrow(UnauthorizedException);
});
it('should pass with valid instance token', async () => {
(req.get as jest.Mock).mockReturnValue('instance-token');
req.params = { instanceName: 'test-instance' };
// Mock prisma repository
jest.spyOn(prismaRepository.instance, 'findUnique').mockResolvedValue({
token: 'instance-token',
} as any);
await authGuard.apikey(req as Request, res as Response, next);
expect(next).toHaveBeenCalled();
});
});
});
```
## Guard Performance Considerations
### Efficient Validation
```typescript
// CORRECT - Efficient guard with early returns
async function efficientGuard(req: Request, _: Response, next: NextFunction) {
// Quick checks first
if (req.originalUrl.includes('/public')) {
return next(); // Skip validation for public routes
}
const apiKey = req.get('apikey');
if (!apiKey) {
throw new UnauthorizedException(); // Fail fast
}
// More expensive checks only if needed
if (apiKey === globalKey) {
return next(); // Skip database check
}
// Database check only as last resort
const isValid = await validateInDatabase(apiKey);
if (isValid) {
return next();
}
throw new UnauthorizedException();
}
// INCORRECT - Inefficient guard
async function inefficientGuard(req: Request, _: Response, next: NextFunction) {
// Always do expensive database check first
const dbResult = await expensiveDatabaseQuery(); // ❌ Expensive operation first
const apiKey = req.get('apikey');
if (!apiKey && dbResult) { // ❌ Complex logic
throw new UnauthorizedException();
}
next();
}
```
================================================
FILE: .cursor/rules/specialized-rules/integration-channel-rules.mdc
================================================
---
description: Channel integration patterns for Evolution API
globs:
- "src/api/integrations/channel/**/*.ts"
alwaysApply: false
---
# Evolution API Channel Integration Rules
## Channel Controller Pattern
### Base Channel Controller
```typescript
export interface ChannelControllerInterface {
integrationEnabled: boolean;
}
export class ChannelController {
public prismaRepository: PrismaRepository;
public waMonitor: WAMonitoringService;
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
this.prisma = prismaRepository;
this.monitor = waMonitor;
}
public set prisma(prisma: PrismaRepository) {
this.prismaRepository = prisma;
}
public get prisma() {
return this.prismaRepository;
}
public set monitor(waMonitor: WAMonitoringService) {
this.waMonitor = waMonitor;
}
public get monitor() {
return this.waMonitor;
}
public init(instanceData: InstanceDto, data: ChannelDataType) {
if (!instanceData.token && instanceData.integration === Integration.WHATSAPP_BUSINESS) {
throw new BadRequestException('token is required');
}
if (instanceData.integration === Integration.WHATSAPP_BUSINESS) {
return new BusinessStartupService(/* dependencies */);
}
if (instanceData.integration === Integration.EVOLUTION) {
return new EvolutionStartupService(/* dependencies */);
}
if (instanceData.integration === Integration.WHATSAPP_BAILEYS) {
return new BaileysStartupService(/* dependencies */);
}
return null;
}
}
```
### Extended Channel Controller
```typescript
export class EvolutionController extends ChannelController implements ChannelControllerInterface {
private readonly logger = new Logger('EvolutionController');
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
super(prismaRepository, waMonitor);
}
integrationEnabled: boolean;
public async receiveWebhook(data: any) {
const numberId = data.numberId;
if (!numberId) {
this.logger.error('WebhookService -> receiveWebhookEvolution -> numberId not found');
return;
}
const instance = await this.prismaRepository.instance.findFirst({
where: { number: numberId },
});
if (!instance) {
this.logger.error('WebhookService -> receiveWebhook -> instance not found');
return;
}
await this.waMonitor.waInstances[instance.name].connectToWhatsapp(data);
return {
status: 'success',
};
}
}
```
## Channel Service Pattern
### Base Channel Service
```typescript
export class ChannelStartupService {
constructor(
private readonly configService: ConfigService,
private readonly eventEmitter: EventEmitter2,
private readonly prismaRepository: PrismaRepository,
public readonly cache: CacheService,
public readonly chatwootCache: CacheService,
) {}
public readonly logger = new Logger('ChannelStartupService');
public client: WASocket;
public readonly instance: wa.Instance = {};
public readonly localChatwoot: wa.LocalChatwoot = {};
public readonly localProxy: wa.LocalProxy = {};
public readonly localSettings: wa.LocalSettings = {};
public readonly localWebhook: wa.LocalWebHook = {};
public setInstance(instance: InstanceDto) {
this.logger.setInstance(instance.instanceName);
this.instance.name = instance.instanceName;
this.instance.id = instance.instanceId;
this.instance.integration = instance.integration;
this.instance.number = instance.number;
this.instance.token = instance.token;
this.instance.businessId = instance.businessId;
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled) {
this.chatwootService.eventWhatsapp(
Events.STATUS_INSTANCE,
{ instanceName: this.instance.name },
{
instance: this.instance.name,
status: 'created',
},
);
}
}
public set instanceName(name: string) {
this.logger.setInstance(name);
this.instance.name = name;
}
public get instanceName() {
return this.instance.name;
}
}
```
### Extended Channel Service
```typescript
export class EvolutionStartupService extends ChannelStartupService {
constructor(
configService: ConfigService,
eventEmitter: EventEmitter2,
prismaRepository: PrismaRepository,
cache: CacheService,
chatwootCache: CacheService,
) {
super(configService, eventEmitter, prismaRepository, cache, chatwootCache);
}
public async sendMessage(data: SendTextDto): Promise<any> {
// Evolution-specific message sending logic
const response = await this.evolutionApiCall('/send-message', data);
return response;
}
public async connectToWhatsapp(data: any): Promise<void> {
// Evolution-specific connection logic
this.logger.log('Connecting to Evolution API');
// Set up webhook listeners
this.setupWebhookHandlers();
// Initialize connection
await this.initializeConnection(data);
}
private async evolutionApiCall(endpoint: string, data: any): Promise<any> {
const config = this.configService.get<Evolution>('EVOLUTION');
try {
const response = await axios.post(`${config.API_URL}${endpoint}`, data, {
headers: {
'Authorization': `Bearer ${this.instance.token}`,
'Content-Type': 'application/json',
},
});
return response.data;
} catch (error) {
this.logger.error(`Evolution API call failed: ${error.message}`);
throw new InternalServerErrorException('Evolution API call failed');
}
}
private setupWebhookHandlers(): void {
// Set up webhook event handlers
}
private async initializeConnection(data: any): Promise<void> {
// Initialize connection with Evolution API
}
}
```
## Business API Service Pattern
### Meta Business Service
```typescript
export class BusinessStartupService extends ChannelStartupService {
constructor(
configService: ConfigService,
eventEmitter: EventEmitter2,
prismaRepository: PrismaRepository,
cache: CacheService,
chatwootCache: CacheService,
baileysCache: CacheService,
providerFiles: ProviderFiles,
) {
super(configService, eventEmitter, prismaRepository, cache, chatwootCache);
}
public async sendMessage(data: SendTextDto): Promise<any> {
const businessConfig = this.configService.get<WaBusiness>('WA_BUSINESS');
const payload = {
messaging_product: 'whatsapp',
to: data.number,
type: 'text',
text: {
body: data.text,
},
};
try {
const response = await axios.post(
`${businessConfig.URL}/${businessConfig.VERSION}/${this.instance.businessId}/messages`,
payload,
{
headers: {
'Authorization': `Bearer ${this.instance.token}`,
'Content-Type': 'application/json',
},
}
);
return response.data;
} catch (error) {
this.logger.error(`Business API call failed: ${error.message}`);
throw new BadRequestException('Failed to send message via Business API');
}
}
public async receiveWebhook(data: any): Promise<void> {
// Process incoming webhook from Meta Business API
const { entry } = data;
for (const entryItem of entry) {
const { changes } = entryItem;
for (const change of changes) {
if (change.field === 'messages') {
await this.processMessage(change.value);
}
}
}
}
private async processMessage(messageData: any): Promise<void> {
// Process incoming message from Business API
const { messages, contacts } = messageData;
if (messages) {
for (const message of messages) {
await this.handleIncomingMessage(message, contacts);
}
}
}
private async handleIncomingMessage(message: any, contacts: any[]): Promise<void> {
// Handle individual message
const contact = contacts?.find(c => c.wa_id === message.from);
// Emit event for message processing
this.eventEmitter.emit(Events.MESSAGES_UPSERT, {
instanceName: this.instance.name,
message,
contact,
});
}
}
```
## Baileys Service Pattern
### Baileys Integration Service
```typescript
export class BaileysStartupService extends ChannelStartupService {
constructor(
configService: ConfigService,
eventEmitter: EventEmitter2,
prismaRepository: PrismaRepository,
cache: CacheService,
chatwootCache: CacheService,
baileysCache: CacheService,
providerFiles: ProviderFiles,
) {
super(configService, eventEmitter, prismaRepository, cache, chatwootCache);
}
public async connectToWhatsapp(): Promise<void> {
const authPath = path.join(INSTANCE_DIR, this.instance.name);
const { state, saveCreds } = await useMultiFileAuthState(authPath);
this.client = makeWASocket({
auth: state,
logger: P({ level: 'error' }),
printQRInTerminal: false,
browser: ['Evolution API', 'Chrome', '4.0.0'],
defaultQueryTimeoutMs: 60000,
});
this.setupEventHandlers();
this.client.ev.on('creds.update', saveCreds);
}
private setupEventHandlers(): void {
this.client.ev.on('connection.update', (update) => {
this.handleConnectionUpdate(update);
});
this.client.ev.on('messages.upsert', ({ messages, type }) => {
this.handleIncomingMessages(messages, type);
});
this.client.ev.on('messages.update', (updates) => {
this.handleMessageUpdates(updates);
});
this.client.ev.on('contacts.upsert', (contacts) => {
this.handleContactsUpdate(contacts);
});
this.client.ev.on('chats.upsert', (chats) => {
this.handleChatsUpdate(chats);
});
}
private async handleConnectionUpdate(update: ConnectionUpdate): Promise<void> {
const { connection, lastDisconnect, qr } = update;
if (qr) {
this.instance.qrcode = {
count: this.instance.qrcode?.count ? this.instance.qrcode.count + 1 : 1,
base64: qr,
};
this.eventEmitter.emit(Events.QRCODE_UPDATED, {
instanceName: this.instance.name,
qrcode: this.instance.qrcode,
});
}
if (connection === 'close') {
const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut;
if (shouldReconnect) {
this.logger.log('Connection closed, reconnecting...');
await this.connectToWhatsapp();
} else {
this.logger.log('Connection closed, logged out');
this.eventEmitter.emit(Events.LOGOUT_INSTANCE, {
instanceName: this.instance.name,
});
}
}
if (connection === 'open') {
this.logger.log('Connection opened successfully');
this.instance.wuid = this.client.user?.id;
this.eventEmitter.emit(Events.CONNECTION_UPDATE, {
instanceName: this.instance.name,
state: 'open',
});
}
}
public async sendMessage(data: SendTextDto): Promise<any> {
const jid = createJid(data.number);
const message = {
text: data.text,
};
if (data.linkPreview !== undefined) {
message.linkPreview = data.linkPreview;
}
if (data.mentionsEveryOne) {
// Handle mentions
}
try {
const response = await this.client.sendMessage(jid, message);
return response;
} catch (error) {
this.logger.error(`Failed to send message: ${error.message}`);
throw new BadRequestException('Failed to send message');
}
}
}
```
## Channel Router Pattern
### Channel Router Structure
```typescript
export class ChannelRouter {
public readonly router: Router;
constructor(configService: any, ...guards: any[]) {
this.router = Router();
this.router.use('/', new EvolutionRouter(configService).router);
this.router.use('/', new MetaRouter(configService).router);
this.router.use('/baileys', new BaileysRouter(...guards).router);
}
}
```
### Specific Channel Router
```typescript
export class EvolutionRouter extends RouterBroker {
constructor(private readonly configService: ConfigService) {
super();
this.router
.post(this.routerPath('webhook'), async (req, res) => {
const response = await evolutionController.receiveWebhook(req.body);
return res.status(HttpStatus.OK).json(response);
});
}
public readonly router: Router = Router();
}
```
## Integration Types
### Channel Data Types
```typescript
type ChannelDataType = {
configService: ConfigService;
eventEmitter: EventEmitter2;
prismaRepository: PrismaRepository;
cache: CacheService;
chatwootCache: CacheService;
baileysCache: CacheService;
providerFiles: ProviderFiles;
};
export enum Integration {
WHATSAPP_BUSINESS = 'WHATSAPP-BUSINESS',
WHATSAPP_BAILEYS = 'WHATSAPP-BAILEYS',
EVOLUTION = 'EVOLUTION',
}
```
## Error Handling in Channels
### Channel-Specific Error Handling
```typescript
// CORRECT - Channel-specific error handling
public async sendMessage(data: SendTextDto): Promise<any> {
try {
const response = await this.channelSpecificSend(data);
return response;
} catch (error) {
this.logger.error(`${this.constructor.name} send failed: ${error.message}`);
if (error.response?.status === 401) {
throw new UnauthorizedException('Invalid token for channel');
}
if (error.response?.status === 429) {
throw new BadRequestException('Rate limit exceeded');
}
throw new InternalServerErrorException('Channel communication failed');
}
}
```
## Channel Testing Pattern
### Channel Service Testing
```typescript
describe('EvolutionStartupService', () => {
let service: EvolutionStartupService;
let configService: jest.Mocked<ConfigService>;
let eventEmitter: jest.Mocked<EventEmitter2>;
beforeEach(() => {
const mockConfig = {
get: jest.fn().mockReturnValue({
API_URL: 'https://api.evolution.com',
}),
};
service = new EvolutionStartupService(
mockConfig as any,
eventEmitter,
prismaRepository,
cache,
chatwootCache,
);
});
describe('sendMessage', () => {
it('should send message successfully', async () => {
const data = { number: '5511999999999', text: 'Test message' };
// Mock axios response
jest.spyOn(axios, 'post').mockResolvedValue({
data: { success: true, messageId: '123' },
});
const result = await service.sendMessage(data);
expect(result.success).toBe(true);
expect(axios.post).toHaveBeenCalledWith(
expect.stringContaining('/send-message'),
data,
expect.objectContaining({
headers: expect.objectContaining({
'Authorization': expect.stringContaining('Bearer'),
}),
})
);
});
});
});
```
================================================
FILE: .cursor/rules/specialized-rules/integration-chatbot-rules.mdc
================================================
---
description: Chatbot integration patterns for Evolution API
globs:
- "src/api/integrations/chatbot/**/*.ts"
alwaysApply: false
---
# Evolution API Chatbot Integration Rules
## Base Chatbot Pattern
### Base Chatbot DTO
```typescript
/**
* Base DTO for all chatbot integrations
* Contains common properties shared by all chatbot types
*/
export class BaseChatbotDto {
enabled?: boolean;
description: string;
expire?: number;
keywordFinish?: string;
delayMessage?: number;
unknownMessage?: string;
listeningFromMe?: boolean;
stopBotFromMe?: boolean;
keepOpen?: boolean;
debounceTime?: number;
triggerType: TriggerType;
triggerOperator?: TriggerOperator;
triggerValue?: string;
ignoreJids?: string[];
splitMessages?: boolean;
timePerChar?: number;
}
```
### Base Chatbot Controller
```typescript
export abstract class BaseChatbotController<BotType = any, BotData extends BaseChatbotDto = BaseChatbotDto>
extends ChatbotController
implements ChatbotControllerInterface
{
public readonly logger: Logger;
integrationEnabled: boolean;
botRepository: any;
settingsRepository: any;
sessionRepository: any;
userMessageDebounce: { [key: string]: { message: string; timeoutId: NodeJS.Timeout } } = {};
// Abstract methods to be implemented by specific chatbots
protected abstract readonly integrationName: string;
protected abstract processBot(
waInstance: any,
remoteJid: string,
bot: BotType,
session: any,
settings: ChatbotSettings,
content: string,
pushName?: string,
msg?: any,
): Promise<void>;
protected abstract getFallbackBotId(settings: any): string | undefined;
constructor(prismaRepository: PrismaRepository, waMonitor: WAMonitoringService) {
super(prismaRepository, waMonitor);
this.sessionRepository = this.prismaRepository.integrationSession;
}
// Base implementation methods
public async createBot(instance: InstanceDto, data: BotData) {
if (!data.enabled) {
throw new BadRequestException(`${this.integrationName} is disabled`);
}
// Common bot creation logic
const bot = await this.botRepository.create({
data: {
...data,
instanceId: instance.instanceId,
},
});
return bot;
}
}
```
### Base Chatbot Service
```typescript
/**
* Base class for all chatbot service implementations
* Contains common methods shared across different chatbot integrations
*/
export abstract class BaseChatbotService<BotType = any, SettingsType = any> {
protected readonly logger: Logger;
protected readonly waMonitor: WAMonitoringService;
protected readonly prismaRepository: PrismaRepository;
protected readonly configService?: ConfigService;
constructor(
waMonitor: WAMonitoringService,
prismaRepository: PrismaRepository,
loggerName: string,
configService?: ConfigService,
) {
this.waMonitor = waMonitor;
this.prismaRepository = prismaRepository;
this.logger = new Logger(loggerName);
this.configService = configService;
}
/**
* Check if a message contains an image
*/
protected isImageMessage(content: string): boolean {
return content.includes('imageMessage');
}
/**
* Extract text content from message
*/
protected getMessageContent(msg: any): string {
return getConversationMessage(msg);
}
/**
* Send typing indicator
*/
protected async sendTyping(instanceName: string, remoteJid: string): Promise<void> {
await this.waMonitor.waInstances[instanceName].sendPresence(remoteJid, 'composing');
}
}
```
## Typebot Integration Pattern
### Typebot Service
```typescript
export class TypebotService extends BaseChatbotService<TypebotModel, any> {
constructor(
waMonitor: WAMonitoringService,
configService: ConfigService,
prismaRepository: PrismaRepository,
private readonly openaiService: OpenaiService,
) {
super(waMonitor, prismaRepository, 'TypebotService', configService);
}
public async sendTypebotMessage(
instanceName: string,
remoteJid: string,
typebot: TypebotModel,
content: string,
): Promise<void> {
try {
const response = await axios.post(
`${typebot.url}/api/v1/typebots/${typebot.typebot}/startChat`,
{
message: content,
sessionId: `${instanceName}-${remoteJid}`,
},
{
headers: {
'Content-Type': 'application/json',
},
}
);
const { messages } = response.data;
for (const message of messages) {
await this.processTypebotMessage(instanceName, remoteJid, message);
}
} catch (error) {
this.logger.error(`Typebot API error: ${error.message}`);
throw new InternalServerErrorException('Typebot communication failed');
}
}
private async processTypebotMessage(
instanceName: string,
remoteJid: string,
message: any,
): Promise<void> {
const waInstance = this.waMonitor.waInstances[instanceName];
if (message.type === 'text') {
await waInstance.sendMessage({
number: remoteJid.split('@')[0],
text: message.content.richText[0].children[0].text,
});
}
if (message.type === 'image') {
await waInstance.sendMessage({
number: remoteJid.split('@')[0],
mediaMessage: {
mediatype: 'image',
media: message.content.url,
},
});
}
}
}
```
## OpenAI Integration Pattern
### OpenAI Service
```typescript
export class OpenaiService extends BaseChatbotService<OpenaiModel, any> {
constructor(
waMonitor: WAMonitoringService,
prismaRepository: PrismaRepository,
configService: ConfigService,
) {
super(waMonitor, prismaRepository, 'OpenaiService', configService);
}
public async sendOpenaiMessage(
instanceName: string,
remoteJid: string,
openai: OpenaiModel,
content: string,
pushName?: string,
): Promise<void> {
try {
const openaiConfig = this.configService.get<Openai>('OPENAI');
const response = await axios.post(
'https://api.openai.com/v1/chat/completions',
{
model: openai.model || 'gpt-3.5-turbo',
messages: [
{
role: 'system',
content: openai.systemMessage || 'You are a helpful assistant.',
},
{
role: 'user',
content: content,
},
],
max_tokens: openai.maxTokens || 1000,
temperature: openai.temperature || 0.7,
},
{
headers: {
'Authorization': `Bearer ${openai.apiKey || openaiConfig.API_KEY}`,
'Content-Type': 'application/json',
},
}
);
const aiResponse = response.data.choices[0].message.content;
await this.waMonitor.waInstances[instanceName].sendMessage({
number: remoteJid.split('@')[0],
text: aiResponse,
});
} catch (error) {
this.logger.error(`OpenAI API error: ${error.message}`);
// Send fallback message
await this.waMonitor.waInstances[instanceName].sendMessage({
number: remoteJid.split('@')[0],
text: openai.unknownMessage || 'Desculpe, não consegui processar sua mensagem.',
});
}
}
}
```
## Chatwoot Integration Pattern
### Chatwoot Service
```typescript
export class ChatwootService extends BaseChatbotService<any, any> {
constructor(
waMonitor: WAMonitoringService,
configService: ConfigService,
prismaRepository: PrismaRepository,
private readonly chatwootCache: CacheService,
) {
super(waMonitor, prismaRepository, 'ChatwootService', configService);
}
public async eventWhatsapp(
event: Events,
instanceName: { instanceName: string },
data: any,
): Promise<void> {
const chatwootConfig = this.configService.get<Chatwoot>('CHATWOOT');
if (!chatwootConfig.ENABLED) {
return;
}
try {
const instance = await this.prismaRepository.instance.findUnique({
where: { name: instanceName.instanceName },
});
if (!instance?.chatwootAccountId) {
return;
}
const webhook = {
event,
instance: instanceName.instanceName,
data,
timestamp: new Date().toISOString(),
};
await axios.post(
`${instance.chatwootUrl}/api/v1/accounts/${instance.chatwootAccountId}/webhooks`,
webhook,
{
headers: {
'Authorization': `Bearer ${instance.chatwootToken}`,
'Content-Type': 'application/json',
},
}
);
} catch (error) {
this.logger.error(`Chatwoot webhook error: ${error.message}`);
}
}
public async createConversation(
instanceName: string,
contact: any,
message: any,
): Promise<void> {
// Create conversation in Chatwoot
const instance = await this.prismaRepository.instance.findUnique({
where: { name: instanceName },
});
if (!instance?.chatwootAccountId) {
return;
}
try {
const conversation = await axios.post(
`${instance.chatwootUrl}/api/v1/accounts/${instance.chatwootAccountId}/conversations`,
{
source_id: contact.id,
inbox_id: instance.chatwootInboxId,
contact_id: contact.chatwootContactId,
},
{
headers: {
'Authorization': `Bearer ${instance.chatwootToken}`,
'Content-Type': 'application/json',
},
}
);
// Cache conversation
await this.chatwootCache.set(
`conversation:${instanceName}:${contact.id}`,
conversation.data,
3600
);
} catch (error) {
this.logger.error(`Chatwoot conversation creation error: ${error.message}`);
}
}
}
```
## Dify Integration Pattern
### Dify Service
```typescript
export class DifyService extends BaseChatbotService<DifyModel, any> {
constructor(
waMonitor: WAMonitoringService,
prismaRepository: PrismaRepository,
configService: ConfigService,
private readonly openaiService: OpenaiService,
) {
super(waMonitor, prismaRepository, 'DifyService', configService);
}
public async sendDifyMessage(
instanceName: string,
remoteJid: string,
dify: DifyModel,
content: string,
): Promise<void> {
try {
const response = await axios.post(
`${dify.apiUrl}/v1/chat-messages`,
{
inputs: {},
query: content,
user: remoteJid,
conversation_id: `${instanceName}-${remoteJid}`,
response_mode: 'blocking',
},
{
headers: {
'Authorization': `Bearer ${dify.apiKey}`,
'Content-Type': 'application/json',
},
}
);
const aiResponse = response.data.answer;
await this.waMonitor.waInstances[instanceName].sendMessage({
number: remoteJid.split('@')[0],
text: aiResponse,
});
} catch (error) {
this.logger.error(`Dify API error: ${error.message}`);
// Fallback to OpenAI if configured
if (dify.fallbackOpenai && this.openaiService) {
await this.openaiService.sendOpenaiMessage(instanceName, remoteJid, dify.openaiBot, content);
}
}
}
}
```
## Chatbot Router Pattern
### Chatbot Router Structure (Evolution API Real Pattern)
```typescript
export class ChatbotRouter {
public readonly router: Router;
constructor(...guards: any[]) {
this.router = Router();
// Real Evolution API chatbot integrations
this.router.use('/evolutionBot', new EvolutionBotRouter(...guards).router);
this.router.use('/chatwoot', new ChatwootRouter(...guards).router);
this.router.use('/typebot', new TypebotRouter(...guards).router);
this.router.use('/openai', new OpenaiRouter(...guards).router);
this.router.use('/dify', new DifyRouter(...guards).router);
this.router.use('/flowise', new FlowiseRouter(...guards).router);
this.router.use('/n8n', new N8nRouter(...guards).router);
this.router.use('/evoai', new EvoaiRouter(...guards).router);
}
}
```
## Chatbot Validation Patterns
### Chatbot Schema Validation (Evolution API Pattern)
```typescript
import { JSONSchema7 } from 'json-schema';
import { v4 } from 'uuid';
const isNotEmpty = (...fields: string[]) => {
const properties = {};
fields.forEach((field) => {
properties[field] = {
if: { properties: { [field]: { type: 'string' } } },
then: { properties: { [field]: { minLength: 1 } } },
};
});
return {
allOf: Object.values(properties),
};
};
export const evolutionBotSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
enabled: { type: 'boolean' },
description: { type: 'string' },
apiUrl: { type: 'string' },
apiKey: { type: 'string' },
triggerType: { type: 'string', enum: ['all', 'keyword', 'none', 'advanced'] },
triggerOperator: { type: 'string', enum: ['equals', 'contains', 'startsWith', 'endsWith', 'regex'] },
triggerValue: { type: 'string' },
expire: { type: 'integer' },
keywordFinish: { type: 'string' },
delayMessage: { type: 'integer' },
unknownMessage: { type: 'string' },
listeningFromMe: { type: 'boolean' },
stopBotFromMe: { type: 'boolean' },
keepOpen: { type: 'boolean' },
debounceTime: { type: 'integer' },
ignoreJids: { type: 'array', items: { type: 'string' } },
splitMessages: { type: 'boolean' },
timePerChar: { type: 'integer' },
},
required: ['enabled', 'apiUrl', 'triggerType'],
...isNotEmpty('enabled', 'apiUrl', 'triggerType'),
};
function validateKeywordTrigger(
content: string,
operator: TriggerOperator,
value: string,
): boolean {
const normalizedContent = content.toLowerCase().trim();
const normalizedValue = value.toLowerCase().trim();
switch (operator) {
case TriggerOperator.EQUALS:
return normalizedContent === normalizedValue;
case TriggerOperator.CONTAINS:
return normalizedContent.includes(normalizedValue);
case TriggerOperator.STARTS_WITH:
return normalizedContent.startsWith(normalizedValue);
case TriggerOperator.ENDS_WITH:
return normalizedContent.endsWith(normalizedValue);
default:
return false;
}
}
```
## Session Management Pattern
### Chatbot Session Handling
```typescript
export class ChatbotSessionManager {
constructor(
private readonly prismaRepository: PrismaRepository,
private readonly cache: CacheService,
) {}
public async getSession(
instanceName: string,
remoteJid: string,
botId: string,
): Promise<IntegrationSession | null> {
const cacheKey = `session:${instanceName}:${remoteJid}:${botId}`;
// Try cache first
let session = await this.cache.get(cacheKey);
if (session) {
return session;
}
// Query database
session = await this.prismaRepository.integrationSession.findFirst({
where: {
instanceId: instanceName,
remoteJid,
botId,
status: 'opened',
},
});
// Cache result
if (session) {
await this.cache.set(cacheKey, session, 300); // 5 min TTL
}
return session;
}
public async createSession(
instanceName: string,
remoteJid: string,
botId: string,
): Promise<IntegrationSession> {
const session = await this.prismaRepository.integrationSession.create({
data: {
instanceId: instanceName,
remoteJid,
botId,
status: 'opened',
createdAt: new Date(),
},
});
// Cache new session
const cacheKey = `session:${instanceName}:${remoteJid}:${botId}`;
await this.cache.set(cacheKey, session, 300);
return session;
}
public async closeSession(sessionId: string): Promise<void> {
await this.prismaRepository.integrationSession.update({
where: { id: sessionId },
data: { status: 'closed', updatedAt: new Date() },
});
// Invalidate cache
// Note: In a real implementation, you'd need to track cache keys by session ID
}
}
```
================================================
FILE: .cursor/rules/specialized-rules/integration-event-rules.mdc
================================================
---
description: Event integration patterns for Evolution API
globs:
- "src/api/integrations/event/**/*.ts"
alwaysApply: false
---
# Evolution API Event Integration Rules
## Event Manager Pattern
### Event Manager Structure
```typescript
import { PrismaRepository } from '@api/repository/repository.service';
import { ConfigService } from '@config/env.config';
import { Logger } from '@config/logger.config';
import { Server } from 'http';
export class EventManager {
private prismaRepository: PrismaRepository;
private configService: ConfigService;
private logger = new Logger('EventManager');
// Event integrations
private webhook: WebhookController;
private websocket: WebsocketController;
private rabbitmq: RabbitmqController;
private nats: NatsController;
private sqs: SqsController;
private pusher: PusherController;
constructor(
prismaRepository: PrismaRepository,
configService: ConfigService,
server?: Server,
) {
this.prismaRepository = prismaRepository;
this.configService = configService;
// Initialize event controllers
this.webhook = new WebhookController(prismaRepository, configService);
this.websocket = new WebsocketController(prismaRepository, configService, server);
this.rabbitmq = new RabbitmqController(prismaRepository, configService);
this.nats = new NatsController(prismaRepository, configService);
this.sqs = new SqsController(prismaRepository, configService);
this.pusher = new PusherController(prismaRepository, configService);
}
public async emit(eventData: {
instanceName: string;
origin: string;
event: string;
data: Object;
serverUrl: string;
dateTime: string;
sender: string;
apiKey?: string;
local?: boolean;
integration?: string[];
}): Promise<void> {
this.logger.log(`Emitting event ${eventData.event} for instance ${eventData.instanceName}`);
// Emit to all configured integrations
await Promise.allSettled([
this.webhook.emit(eventData),
this.websocket.emit(eventData),
this.rabbitmq.emit(eventData),
this.nats.emit(eventData),
this.sqs.emit(eventData),
this.pusher.emit(eventData),
]);
}
public async setInstance(instanceName: string, data: any): Promise<any> {
const promises = [];
if (data.websocket) {
promises.push(
this.websocket.set(instanceName, {
websocket: {
enabled: true,
events: data.websocket?.events,
},
})
);
}
if (data.rabbitmq) {
promises.push(
this.rabbitmq.set(instanceName, {
rabbitmq: {
enabled: true,
events: data.rabbitmq?.events,
},
})
);
}
if (data.webhook) {
promises.push(
this.webhook.set(instanceName, {
webhook: {
enabled: true,
events: data.webhook?.events,
url: data.webhook?.url,
headers: data.webhook?.headers,
base64: data.webhook?.base64,
byEvents: data.webhook?.byEvents,
},
})
);
}
// Set other integrations...
await Promise.allSettled(promises);
}
}
```
## Base Event Controller Pattern
### Abstract Event Controller
```typescript
import { PrismaRepository } from '@api/repository/repository.service';
import { ConfigService } from '@config/env.config';
import { Logger } from '@config/logger.config';
export type EmitData = {
instanceName: string;
origin: string;
event: string;
data: Object;
serverUrl: string;
dateTime: string;
sender: string;
apiKey?: string;
local?: boolean;
integration?: string[];
};
export interface EventControllerInterface {
integrationEnabled: boolean;
emit(data: EmitData): Promise<void>;
set(instanceName: string, data: any): Promise<any>;
}
export abstract class EventController implements EventControllerInterface {
protected readonly logger: Logger;
protected readonly prismaRepository: PrismaRepository;
protected readonly configService: ConfigService;
public integrationEnabled: boolean = false;
// Available events for all integrations
public static readonly events = [
'APPLICATION_STARTUP',
'INSTANCE_CREATE',
'INSTANCE_DELETE',
'QRCODE_UPDATED',
'CONNECTION_UPDATE',
'STATUS_INSTANCE',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_EDITED',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPDATE',
'CHATS_UPSERT',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUPS_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CALL',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CREDS_UPDATE',
'MESSAGING_HISTORY_SET',
'REMOVE_INSTANCE',
'LOGOUT_INSTANCE',
];
constructor(
prismaRepository: PrismaRepository,
configService: ConfigService,
loggerName: string,
) {
this.prismaRepository = prismaRepository;
this.configService = configService;
this.logger = new Logger(loggerName);
}
// Abstract methods to be implemented by specific integrations
public abstract emit(data: EmitData): Promise<void>;
public abstract set(instanceName: string, data: any): Promise<any>;
// Helper method to check if event should be processed
protected shouldProcessEvent(eventName: string, configuredEvents?: string[]): boolean {
if (!configuredEvents || configuredEvents.length === 0) {
return true; // Process all events if none specified
}
return configuredEvents.includes(eventName);
}
// Helper method to get instance configuration
protected async getInstanceConfig(instanceName: string): Promise<any> {
try {
const instance = await this.prismaRepository.instance.findUnique({
where: { name: instanceName },
});
return instance;
} catch (error) {
this.logger.error(`Failed to get instance config for ${instanceName}:`, error);
return null;
}
}
}
```
## Webhook Integration Pattern
### Webhook Controller Implementation
```typescript
export class WebhookController extends EventController {
constructor(
prismaRepository: PrismaRepository,
configService: ConfigService,
) {
super(prismaRepository, configService, 'WebhookController');
}
public async emit(data: EmitData): Promise<void> {
try {
const instance = await this.getInstanceConfig(data.instanceName);
if (!instance?.webhook?.enabled) {
return;
}
const webhookConfig = instance.webhook;
if (!this.shouldProcessEvent(data.event, webhookConfig.events)) {
return;
}
const payload = {
event: data.event,
instance: data.instanceName,
data: data.data,
timestamp: data.dateTime,
sender: data.sender,
server: {
version: process.env.npm_package_version,
url: data.serverUrl,
},
};
// Encode data as base64 if configured
if (webhookConfig.base64) {
payload.data = Buffer.from(JSON.stringify(payload.data)).toString('base64');
}
const headers = {
'Content-Type': 'application/json',
'User-Agent': 'Evolution-API-Webhook',
...webhookConfig.headers,
};
if (webhookConfig.byEvents) {
// Send to event-specific endpoint
const eventUrl = `${webhookConfig.url}/${data.event.toLowerCase()}`;
await this.sendWebhook(eventUrl, payload, headers);
} else {
// Send to main webhook URL
await this.sendWebhook(webhookConfig.url, payload, headers);
}
this.logger.log(`Webhook sent for event ${data.event} to instance ${data.instanceName}`);
} catch (error) {
this.logger.error(`Webhook emission failed for ${data.instanceName}:`, error);
}
}
public async set(instanceName: string, data: any): Promise<any> {
try {
const webhookData = data.webhook;
await this.prismaRepository.instance.update({
where: { name: instanceName },
data: {
webhook: webhookData,
},
});
this.logger.log(`Webhook configuration set for instance ${instanceName}`);
return { webhook: webhookData };
} catch (error) {
this.logger.error(`Failed to set webhook config for ${instanceName}:`, error);
throw error;
}
}
private async sendWebhook(url: string, payload: any, headers: any): Promise<void> {
try {
const response = await axios.post(url, payload, {
headers,
timeout: 30000,
maxRedirects: 3,
});
if (response.status >= 200 && response.status < 300) {
this.logger.log(`Webhook delivered successfully to ${url}`);
} else {
this.logger.warn(`Webhook returned status ${response.status} for ${url}`);
}
} catch (error) {
this.logger.error(`Webhook delivery failed to ${url}:`, error.message);
// Implement retry logic here if needed
if (error.response?.status >= 500) {
// Server error - might be worth retrying
this.logger.log(`Server error detected, webhook might be retried later`);
}
}
}
}
```
## WebSocket Integration Pattern
### WebSocket Controller Implementation
```typescript
import { Server as SocketIOServer } from 'socket.io';
import { Server } from 'http';
export class WebsocketController extends EventController {
private io: SocketIOServer;
constructor(
prismaRepository: PrismaRepository,
configService: ConfigService,
server?: Server,
) {
super(prismaRepository, configService, 'WebsocketController');
if (server) {
this.io = new SocketIOServer(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
},
});
this.setupSocketHandlers();
}
}
private setupSocketHandlers(): void {
this.io.on('connection', (socket) => {
this.logger.log(`WebSocket client connected: ${socket.id}`);
socket.on('join-instance', (instanceName: string) => {
socket.join(`instance:${instanceName}`);
this.logger.log(`Client ${socket.id} joined instance ${instanceName}`);
});
socket.on('leave-instance', (instanceName: string) => {
socket.leave(`instance:${instanceName}`);
this.logger.log(`Client ${socket.id} left instance ${instanceName}`);
});
socket.on('disconnect', () => {
this.logger.log(`WebSocket client disconnected: ${socket.id}`);
});
});
}
public async emit(data: EmitData): Promise<void> {
if (!this.io) {
return;
}
try {
const instance = await this.getInstanceConfig(data.instanceName);
if (!instance?.websocket?.enabled) {
return;
}
const websocketConfig = instance.websocket;
if (!this.shouldProcessEvent(data.event, websocketConfig.events)) {
return;
}
const payload = {
event: data.event,
instance: data.instanceName,
data: data.data,
timestamp: data.dateTime,
sender: data.sender,
};
// Emit to specific instance room
this.io.to(`instance:${data.instanceName}`).emit('evolution-event', payload);
// Also emit to global room for monitoring
this.io.emit('global-event', payload);
this.logger.log(`WebSocket event ${data.event} emitted for instance ${data.instanceName}`);
} catch (error) {
this.logger.error(`WebSocket emission failed for ${data.instanceName}:`, error);
}
}
public async set(instanceName: string, data: any): Promise<any> {
try {
const websocketData = data.websocket;
await this.prismaRepository.instance.update({
where: { name: instanceName },
data: {
websocket: websocketData,
},
});
this.logger.log(`WebSocket configuration set for instance ${instanceName}`);
return { websocket: websocketData };
} catch (error) {
this.logger.error(`Failed to set WebSocket config for ${instanceName}:`, error);
throw error;
}
}
}
```
## Queue Integration Patterns
### RabbitMQ Controller Implementation
```typescript
import amqp from 'amqplib';
export class RabbitmqController extends EventController {
private connection: amqp.Connection | null = null;
private channel: amqp.Channel | null = null;
constructor(
prismaRepository: PrismaRepository,
configService: ConfigService,
) {
super(prismaRepository, configService, 'RabbitmqController');
this.initializeConnection();
}
private async initializeConnection(): Promise<void> {
try {
const rabbitmqConfig = this.configService.get('RABBITMQ');
if (!rabbitmqConfig?.ENABLED) {
return;
}
this.connection = await amqp.connect(rabbitmqConfig.URI);
this.channel = await this.connection.createChannel();
// Declare exchange for Evolution API events
await this.channel.assertExchange('evolution-events', 'topic', { durable: true });
this.logger.log('RabbitMQ connection established');
} catch (error) {
this.logger.error('Failed to initialize RabbitMQ connection:', error);
}
}
public async emit(data: EmitData): Promise<void> {
if (!this.channel) {
return;
}
try {
const instance = await this.getInstanceConfig(data.instanceName);
if (!instance?.rabbitmq?.enabled) {
return;
}
const rabbitmqConfig = instance.rabbitmq;
if (!this.shouldProcessEvent(data.event, rabbitmqConfig.events)) {
return;
}
const payload = {
event: data.event,
instance: data.instanceName,
data: data.data,
timestamp: data.dateTime,
sender: data.sender,
};
const routingKey = `evolution.${data.instanceName}.${data.event.toLowerCase()}`;
await this.channel.publish(
'evolution-events',
routingKey,
Buffer.from(JSON.stringify(payload)),
{
persistent: true,
timestamp: Date.now(),
messageId: `${data.instanceName}-${Date.now()}`,
}
);
this.logger.log(`RabbitMQ message published for event ${data.event} to instance ${data.instanceName}`);
} catch (error) {
this.logger.error(`RabbitMQ emission failed for ${data.instanceName}:`, error);
}
}
public async set(instanceName: string, data: any): Promise<any> {
try {
const rabbitmqData = data.rabbitmq;
await this.prismaRepository.instance.update({
where: { name: instanceName },
data: {
rabbitmq: rabbitmqData,
},
});
this.logger.log(`RabbitMQ configuration set for instance ${instanceName}`);
return { rabbitmq: rabbitmqData };
} catch (error) {
this.logger.error(`Failed to set RabbitMQ config for ${instanceName}:`, error);
throw error;
}
}
}
```
### SQS Controller Implementation
```typescript
import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs';
export class SqsController extends EventController {
private sqsClient: SQSClient | null = null;
constructor(
prismaRepository: PrismaRepository,
configService: ConfigService,
) {
super(prismaRepository, configService, 'SqsController');
this.initializeSQSClient();
}
private initializeSQSClient(): void {
try {
const sqsConfig = this.configService.get('SQS');
if (!sqsConfig?.ENABLED) {
return;
}
this.sqsClient = new SQSClient({
region: sqsConfig.REGION,
credentials: {
accessKeyId: sqsConfig.ACCESS_KEY_ID,
secretAccessKey: sqsConfig.SECRET_ACCESS_KEY,
},
});
this.logger.log('SQS client initialized');
} catch (error) {
this.logger.error('Failed to initialize SQS client:', error);
}
}
public async emit(data: EmitData): Promise<void> {
if (!this.sqsClient) {
return;
}
try {
const instance = await this.getInstanceConfig(data.instanceName);
if (!instance?.sqs?.enabled) {
return;
}
const sqsConfig = instance.sqs;
if (!this.shouldProcessEvent(data.event, sqsConfig.events)) {
return;
}
const payload = {
event: data.event,
instance: data.instanceName,
data: data.data,
timestamp: data.dateTime,
sender: data.sender,
};
const command = new SendMessageCommand({
QueueUrl: sqsConfig.queueUrl,
MessageBody: JSON.stringify(payload),
MessageAttributes: {
event: {
DataType: 'String',
StringValue: data.event,
},
instance: {
DataType: 'String',
StringValue: data.instanceName,
},
},
MessageGroupId: data.instanceName, // For FIFO queues
MessageDeduplicationId: `${data.instanceName}-${Date.now()}`, // For FIFO queues
});
await this.sqsClient.send(command);
this.logger.log(`SQS message sent for event ${data.event} to instance ${data.instanceName}`);
} catch (error) {
this.logger.error(`SQS emission failed for ${data.instanceName}:`, error);
}
}
public async set(instanceName: string, data: any): Promise<any> {
try {
const sqsData = data.sqs;
await this.prismaRepository.instance.update({
where: { name: instanceName },
data: {
sqs: sqsData,
},
});
this.logger.log(`SQS configuration set for instance ${instanceName}`);
return { sqs: sqsData };
} catch (error) {
this.logger.error(`Failed to set SQS config for ${instanceName}:`, error);
throw error;
}
}
}
```
## Event DTO Pattern
### Event Configuration DTO
```typescript
import { JsonValue } from '@prisma/client/runtime/library';
export class EventDto {
webhook?: {
enabled?: boolean;
events?: string[];
url?: string;
headers?: JsonValue;
byEvents?: boolean;
base64?: boolean;
};
websocket?: {
enabled?: boolean;
events?: string[];
};
sqs?: {
enabled?: boolean;
events?: string[];
queueUrl?: string;
};
rabbitmq?: {
enabled?: boolean;
events?: string[];
exchange?: string;
};
nats?: {
enabled?: boolean;
events?: string[];
subject?: string;
};
pusher?: {
enabled?: boolean;
appId?: string;
key?: string;
secret?: string;
cluster?: string;
useTLS?: boolean;
events?: string[];
};
}
```
## Event Router Pattern
### Event Router Structure
```typescript
import { NatsRouter } from '@api/integrations/event/nats/nats.router';
import { PusherRouter } from '@api/integrations/event/pusher/pusher.router';
import { RabbitmqRouter } from '@api/integrations/event/rabbitmq/rabbitmq.router';
import { SqsRouter } from '@api/integrations/event/sqs/sqs.router';
import { WebhookRouter } from '@api/integrations/event/webhook/webhook.router';
import { WebsocketRouter } from '@api/integrations/event/websocket/websocket.router';
import { Router } from 'express';
export class EventRouter {
public readonly router: Router;
constructor(configService: any, ...guards: any[]) {
this.router = Router();
this.router.use('/webhook', new WebhookRouter(configService, ...guards).router);
this.router.use('/websocket', new WebsocketRouter(...guards).router);
this.router.use('/rabbitmq', new RabbitmqRouter(...guards).router);
this.router.use('/nats', new NatsRouter(...guards).router);
this.router.use('/pusher', new PusherRouter(...guards).router);
this.router.use('/sqs', new SqsRouter(...guards).router);
}
}
```
## Event Validation Schema
### Event Configuration Validation
```typescript
import Joi from 'joi';
import { EventController } from '@api/integrations/event/event.controller';
const eventListSchema = Joi.array().items(
Joi.string().valid(...EventController.events)
).optional();
export const webhookSchema = Joi.object({
enabled: Joi.boolean().required(),
url: Joi.string().when('enabled', {
is: true,
then: Joi.required().uri({ scheme: ['http', 'https'] }),
otherwise: Joi.optional(),
}),
events: eventListSchema,
headers: Joi.object().pattern(Joi.string(), Joi.string()).optional(),
byEvents: Joi.boolean().optional().default(false),
base64: Joi.boolean().optional().default(false),
}).required();
export const websocketSchema = Joi.object({
enabled: Joi.boolean().required(),
events: eventListSchema,
}).required();
export const rabbitmqSchema = Joi.object({
enabled: Joi.boolean().required(),
events: eventListSchema,
exchange: Joi.string().optional().default('evolution-events'),
}).required();
export const sqsSchema = Joi.object({
enabled: Joi.boolean().required(),
events: eventListSchema,
queueUrl: Joi.string().when('enabled', {
is: true,
then: Joi.required().uri(),
otherwise: Joi.optional(),
}),
}).required();
export const eventSchema = Joi.object({
webhook: webhookSchema.optional(),
websocket: websocketSchema.optional(),
rabbitmq: rabbitmqSchema.optional(),
sqs: sqsSchema.optional(),
nats: Joi.object({
enabled: Joi.boolean().required(),
events: eventListSchema,
subject: Joi.string().optional().default('evolution.events'),
}).optional(),
pusher: Joi.object({
enabled: Joi.boolean().required(),
appId: Joi.string().when('enabled', { is: true, then: Joi.required() }),
key: Joi.string().when('enabled', { is: true, then: Joi.required() }),
secret: Joi.string().when('enabled', { is: true, then: Joi.required() }),
cluster: Joi.string().when('enabled', { is: true, then: Joi.required() }),
useTLS: Joi.boolean().optional().default(true),
events: eventListSchema,
}).optional(),
}).min(1).required();
```
## Event Testing Pattern
### Event Controller Testing
```typescript
describe('WebhookController', () => {
let controller: WebhookController;
let prismaRepository: jest.Mocked<PrismaRepository>;
let configService: jest.Mocked<ConfigService>;
beforeEach(() => {
controller = new WebhookController(prismaRepository, configService);
});
describe('emit', () => {
it('should send webhook when enabled', async () => {
const mockInstance = {
webhook: {
enabled: true,
url: 'https://example.com/webhook',
events: ['MESSAGES_UPSERT'],
},
};
prismaRepository.instance.findUnique.mockResolvedValue(mockInstance);
jest.spyOn(axios, 'post').mockResolvedValue({ status: 200 });
const eventData = {
instanceName: 'test-instance',
event: 'MESSAGES_UPSERT',
data: { message: 'test' },
origin: 'test',
serverUrl: 'http://localhost',
dateTime: new Date().toISOString(),
sender: 'test',
};
await controller.emit(eventData);
expect(axios.post).toHaveBeenCalledWith(
'https://example.com/webhook',
expect.objectContaining({
event: 'MESSAGES_UPSERT',
instance: 'test-instance',
}),
expect.objectContaining({
headers: expect.objectContaining({
'Content-Type': 'application/json',
}),
})
);
});
});
});
```
================================================
FILE: .cursor/rules/specialized-rules/integration-storage-rules.mdc
================================================
---
description: Storage integration patterns for Evolution API
globs:
- "src/api/integrations/storage/**/*.ts"
alwaysApply: false
---
# Evolution API Storage Integration Rules
## Storage Service Pattern
### Base Storage Service Structure
```typescript
import { InstanceDto } from '@api/dto/instance.dto';
import { PrismaRepository } from '@api/repository/repository.service';
import { Logger } from '@config/logger.config';
import { BadRequestException } from '@exceptions';
export class StorageService {
constructor(private readonly prismaRepository: PrismaRepository) {}
private readonly logger = new Logger('StorageService');
public async getMedia(instance: InstanceDto, query?: MediaDto) {
try {
const where: any = {
instanceId: instance.instanceId,
...query,
};
const media = await this.prismaRepository.media.findMany({
where,
select: {
id: true,
fileName: true,
type: true,
mimetype: true,
createdAt: true,
Message: true,
},
});
if (!media || media.length === 0) {
throw 'Media not found';
}
return media;
} catch (error) {
throw new BadRequestException(error);
}
}
public async getMediaUrl(instance: InstanceDto, data: MediaDto) {
const media = (await this.getMedia(instance, { id: data.id }))[0];
const mediaUrl = await this.generateUrl(media.fileName, data.expiry);
return {
mediaUrl,
...media,
};
}
protected abstract generateUrl(fileName: string, expiry?: number): Promise<string>;
}
```
## S3/MinIO Integration Pattern
### MinIO Client Setup
```typescript
import { ConfigService, S3 } from '@config/env.config';
import { Logger } from '@config/logger.config';
import { BadRequestException } from '@exceptions';
import * as MinIo from 'minio';
import { join } from 'path';
import { Readable, Transform } from 'stream';
const logger = new Logger('S3 Service');
const BUCKET = new ConfigService().get<S3>('S3');
interface Metadata extends MinIo.ItemBucketMetadata {
instanceId: string;
messageId?: string;
}
const minioClient = (() => {
if (BUCKET?.ENABLE) {
return new MinIo.Client({
endPoint: BUCKET.ENDPOINT,
port: BUCKET.PORT,
useSSL: BUCKET.USE_SSL,
accessKey: BUCKET.ACCESS_KEY,
secretKey: BUCKET.SECRET_KEY,
region: BUCKET.REGION,
});
}
})();
const bucketName = process.env.S3_BUCKET;
```
### Bucket Management Functions
```typescript
const bucketExists = async (): Promise<boolean> => {
if (minioClient) {
try {
const list = await minioClient.listBuckets();
return !!list.find((bucket) => bucket.name === bucketName);
} catch (error) {
logger.error('Error checking bucket existence:', error);
return false;
}
}
return false;
};
const setBucketPolicy = async (): Promise<void> => {
if (minioClient && bucketName) {
try {
const policy = {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: { AWS: ['*'] },
Action: ['s3:GetObject'],
Resource: [`arn:aws:s3:::${bucketName}/*`],
},
],
};
await minioClient.setBucketPolicy(bucketName, JSON.stringify(policy));
logger.log('Bucket policy set successfully');
} catch (error) {
logger.error('Error setting bucket policy:', error);
}
}
};
const createBucket = async (): Promise<void> => {
if (minioClient && bucketName) {
try {
const exists = await bucketExists();
if (!exists) {
await minioClient.makeBucket(bucketName, BUCKET.REGION || 'us-east-1');
await setBucketPolicy();
logger.log(`Bucket ${bucketName} created successfully`);
}
} catch (error) {
logger.error('Error creating bucket:', error);
}
}
};
```
### File Upload Functions
```typescript
export const uploadFile = async (
fileName: string,
buffer: Buffer,
mimetype: string,
metadata?: Metadata,
): Promise<string> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
await createBucket();
const uploadMetadata = {
'Content-Type': mimetype,
...metadata,
};
await minioClient.putObject(bucketName, fileName, buffer, buffer.length, uploadMetadata);
logger.log(`File ${fileName} uploaded successfully`);
return fileName;
} catch (error) {
logger.error(`Error uploading file ${fileName}:`, error);
throw new BadRequestException(`Failed to upload file: ${error.message}`);
}
};
export const uploadStream = async (
fileName: string,
stream: Readable,
size: number,
mimetype: string,
metadata?: Metadata,
): Promise<string> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
await createBucket();
const uploadMetadata = {
'Content-Type': mimetype,
...metadata,
};
await minioClient.putObject(bucketName, fileName, stream, size, uploadMetadata);
logger.log(`Stream ${fileName} uploaded successfully`);
return fileName;
} catch (error) {
logger.error(`Error uploading stream ${fileName}:`, error);
throw new BadRequestException(`Failed to upload stream: ${error.message}`);
}
};
```
### File Download Functions
```typescript
export const getObject = async (fileName: string): Promise<Buffer> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
const stream = await minioClient.getObject(bucketName, fileName);
const chunks: Buffer[] = [];
return new Promise((resolve, reject) => {
stream.on('data', (chunk) => chunks.push(chunk));
stream.on('end', () => resolve(Buffer.concat(chunks)));
stream.on('error', reject);
});
} catch (error) {
logger.error(`Error getting object ${fileName}:`, error);
throw new BadRequestException(`Failed to get object: ${error.message}`);
}
};
export const getObjectUrl = async (fileName: string, expiry: number = 3600): Promise<string> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
const url = await minioClient.presignedGetObject(bucketName, fileName, expiry);
logger.log(`Generated URL for ${fileName} with expiry ${expiry}s`);
return url;
} catch (error) {
logger.error(`Error generating URL for ${fileName}:`, error);
throw new BadRequestException(`Failed to generate URL: ${error.message}`);
}
};
export const getObjectStream = async (fileName: string): Promise<Readable> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
const stream = await minioClient.getObject(bucketName, fileName);
return stream;
} catch (error) {
logger.error(`Error getting object stream ${fileName}:`, error);
throw new BadRequestException(`Failed to get object stream: ${error.message}`);
}
};
```
### File Management Functions
```typescript
export const deleteObject = async (fileName: string): Promise<void> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
await minioClient.removeObject(bucketName, fileName);
logger.log(`File ${fileName} deleted successfully`);
} catch (error) {
logger.error(`Error deleting file ${fileName}:`, error);
throw new BadRequestException(`Failed to delete file: ${error.message}`);
}
};
export const listObjects = async (prefix?: string): Promise<MinIo.BucketItem[]> => {
if (!minioClient || !bucketName) {
throw new BadRequestException('S3 storage not configured');
}
try {
const objects: MinIo.BucketItem[] = [];
const stream = minioClient.listObjects(bucketName, prefix, true);
return new Promise((resolve, reject) => {
stream.on('data', (obj) => objects.push(obj));
stream.on('end', () => resolve(objects));
stream.on('error', reject);
});
} catch (error) {
logger.error('Error listing objects:', error);
throw new BadRequestException(`Failed to list objects: ${error.message}`);
}
};
export const objectExists = async (fileName: string): Promise<boolean> => {
if (!minioClient || !bucketName) {
return false;
}
try {
await minioClient.statObject(bucketName, fileName);
return true;
} catch (error) {
return false;
}
};
```
## Storage Controller Pattern
### S3 Controller Implementation
```typescript
import { InstanceDto } from '@api/dto/instance.dto';
import { MediaDto } from '@api/integrations/storage/s3/dto/media.dto';
import { S3Service } from '@api/integrations/storage/s3/services/s3.service';
export class S3Controller {
constructor(private readonly s3Service: S3Service) {}
public async getMedia(instance: InstanceDto, data: MediaDto) {
return this.s3Service.getMedia(instance, data);
}
public async getMediaUrl(instance: InstanceDto, data: MediaDto) {
return this.s3Service.getMediaUrl(instance, data);
}
public async uploadMedia(instance: InstanceDto, data: UploadMediaDto) {
return this.s3Service.uploadMedia(instance, data);
}
public async deleteMedia(instance: InstanceDto, data: MediaDto) {
return this.s3Service.deleteMedia(instance, data);
}
}
```
## Storage Router Pattern
### Storage Router Structure
```typescript
import { S3Router } from '@api/integrations/storage/s3/routes/s3.router';
import { Router } from 'express';
export class StorageRouter {
public readonly router: Router;
constructor(...guards: any[]) {
this.router = Router();
this.router.use('/s3', new S3Router(...guards).router);
// Add other storage providers here
// this.router.use('/gcs', new GCSRouter(...guards).router);
// this.router.use('/azure', new AzureRouter(...guards).router);
}
}
```
### S3 Specific Router
```typescript
import { RouterBroker } from '@api/abstract/abstract.router';
import { MediaDto } from '@api/integrations/storage/s3/dto/media.dto';
import { s3Schema, s3UrlSchema } from '@api/integrations/storage/s3/validate/s3.schema';
import { HttpStatus } from '@api/routes/index.router';
import { s3Controller } from '@api/server.module';
import { RequestHandler, Router } from 'express';
export class S3Router extends RouterBroker {
constructor(...guards: RequestHandler[]) {
super();
this.router
.post(this.routerPath('getMedia'), ...guards, async (req, res) => {
const response = await this.dataValidate<MediaDto>({
request: req,
schema: s3Schema,
ClassRef: MediaDto,
execute: (instance, data) => s3Controller.getMedia(instance, data),
});
res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('getMediaUrl'), ...guards, async (req, res) => {
const response = await this.dataValidate<MediaDto>({
request: req,
schema: s3UrlSchema,
ClassRef: MediaDto,
execute: (instance, data) => s3Controller.getMediaUrl(instance, data),
});
res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('uploadMedia'), ...guards, async (req, res) => {
const response = await this.dataValidate<UploadMediaDto>({
request: req,
schema: uploadSchema,
ClassRef: UploadMediaDto,
execute: (instance, data) => s3Controller.uploadMedia(instance, data),
});
res.status(HttpStatus.CREATED).json(response);
})
.delete(this.routerPath('deleteMedia'), ...guards, async (req, res) => {
const response = await this.dataValidate<MediaDto>({
request: req,
schema: s3Schema,
ClassRef: MediaDto,
execute: (instance, data) => s3Controller.deleteMedia(instance, data),
});
res.status(HttpStatus.OK).json(response);
});
}
public readonly router: Router = Router();
}
```
## Storage DTO Pattern
### Media DTO
```typescript
export class MediaDto {
id?: string;
fileName?: string;
type?: string;
mimetype?: string;
expiry?: number;
}
export class UploadMediaDto {
fileName: string;
mimetype: string;
buffer?: Buffer;
base64?: string;
url?: string;
metadata?: {
instanceId: string;
messageId?: string;
contactId?: string;
[key: string]: any;
};
}
```
## Storage Validation Schema
### S3 Validation Schemas
```typescript
import Joi from 'joi';
export const s3Schema = Joi.object({
id: Joi.string().optional(),
fileName: Joi.string().optional(),
type: Joi.string().optional().valid('image', 'video', 'audio', 'document'),
mimetype: Joi.string().optional(),
expiry: Joi.number().optional().min(60).max(604800).default(3600), // 1 min to 7 days
}).min(1).required();
export const s3UrlSchema = Joi.object({
id: Joi.string().required(),
expiry: Joi.number().optional().min(60).max(604800).default(3600),
}).required();
export const uploadSchema = Joi.object({
fileName: Joi.string().required().max(255),
mimetype: Joi.string().required(),
buffer: Joi.binary().optional(),
base64: Joi.string().base64().optional(),
url: Joi.string().uri().optional(),
metadata: Joi.object({
instanceId: Joi.string().required(),
messageId: Joi.string().optional(),
contactId: Joi.string().optional(),
}).optional(),
}).xor('buffer', 'base64', 'url').required(); // Exactly one of these must be present
```
## Error Handling in Storage
### Storage-Specific Error Handling
```typescript
// CORRECT - Storage-specific error handling
public async uploadFile(fileName: string, buffer: Buffer): Promise<string> {
try {
const result = await this.storageClient.upload(fileName, buffer);
return result;
} catch (error) {
this.logger.error(`Storage upload failed: ${error.message}`);
if (error.code === 'NoSuchBucket') {
throw new BadRequestException('Storage bucket not found');
}
if (error.code === 'AccessDenied') {
throw new UnauthorizedException('Storage access denied');
}
if (error.code === 'EntityTooLarge') {
throw new BadRequestException('File too large');
}
throw new InternalServerErrorException('Storage operation failed');
}
}
```
## Storage Configuration Pattern
### Environment Configuration
```typescript
export interface S3Config {
ENABLE: boolean;
ENDPOINT: string;
PORT: number;
USE_SSL: boolean;
ACCESS_KEY: string;
SECRET_KEY: string;
REGION: string;
BUCKET: string;
}
// Usage in service
const s3Config = this.configService.get<S3Config>('S3');
if (!s3Config.ENABLE) {
throw new BadRequestException('S3 storage is disabled');
}
```
## Storage Testing Pattern
### Storage Service Testing
```typescript
describe('S3Service', () => {
let service: S3Service;
let prismaRepository: jest.Mocked<PrismaRepository>;
beforeEach(() => {
service = new S3Service(prismaRepository);
});
describe('getMedia', () => {
it('should return media list', async () => {
const instance = { instanceId: 'test-instance' };
const mockMedia = [
{ id: '1', fileName: 'test.jpg', type: 'image', mimetype: 'image/jpeg' },
];
prismaRepository.media.findMany.mockResolvedValue(mockMedia);
const result = await service.getMedia(instance);
expect(result).toEqual(mockMedia);
expect(prismaRepository.media.findMany).toHaveBeenCalledWith({
where: { instanceId: 'test-instance' },
select: expect.objectContaining({
id: true,
fileName: true,
type: true,
mimetype: true,
}),
});
});
it('should throw error when no media found', async () => {
const instance = { instanceId: 'test-instance' };
prismaRepository.media.findMany.mockResolvedValue([]);
await expect(service.getMedia(instance)).rejects.toThrow(BadRequestException);
});
});
});
```
## Storage Performance Considerations
### Efficient File Handling
```typescript
// CORRECT - Stream-based upload for large files
public async uploadLargeFile(fileName: string, stream: Readable, size: number): Promise<string> {
const uploadStream = new Transform({
transform(chunk, encoding, callback) {
// Optional: Add compression, encryption, etc.
callback(null, chunk);
},
});
return new Promise((resolve, reject) => {
stream
.pipe(uploadStream)
.on('error', reject)
.on('finish', () => resolve(fileName));
});
}
// INCORRECT - Loading entire file into memory
public async uploadLargeFile(fileName: string, filePath: string): Promise<string> {
const buffer = fs.readFileSync(filePath); // ❌ Memory intensive for large files
return await this.uploadFile(fileName, buffer);
}
```
================================================
FILE: .cursor/rules/specialized-rules/route-rules.mdc
================================================
---
description: Router patterns for Evolution API
globs:
- "src/api/routes/**/*.ts"
alwaysApply: false
---
# Evolution API Route Rules
## Router Base Pattern
### RouterBroker Extension
```typescript
import { RouterBroker } from '@api/abstract/abstract.router';
import { RequestHandler, Router } from 'express';
import { HttpStatus } from './index.router';
export class ExampleRouter extends RouterBroker {
constructor(...guards: RequestHandler[]) {
super();
this.router
.get(this.routerPath('findExample'), ...guards, async (req, res) => {
const response = await this.dataValidate<ExampleDto>({
request: req,
schema: null,
ClassRef: ExampleDto,
execute: (instance) => exampleController.find(instance),
});
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('createExample'), ...guards, async (req, res) => {
const response = await this.dataValidate<ExampleDto>({
request: req,
schema: exampleSchema,
ClassRef: ExampleDto,
execute: (instance, data) => exampleController.create(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
});
}
public readonly router: Router = Router();
}
```
## Main Router Pattern
### Index Router Structure
```typescript
import { Router } from 'express';
import { authGuard } from '@api/guards/auth.guard';
import { instanceExistsGuard, instanceLoggedGuard } from '@api/guards/instance.guard';
import Telemetry from '@api/guards/telemetry.guard';
enum HttpStatus {
OK = 200,
CREATED = 201,
NOT_FOUND = 404,
FORBIDDEN = 403,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
INTERNAL_SERVER_ERROR = 500,
}
const router: Router = Router();
const guards = [instanceExistsGuard, instanceLoggedGuard, authGuard['apikey']];
const telemetry = new Telemetry();
router
.use((req, res, next) => telemetry.collectTelemetry(req, res, next))
.get('/', async (req, res) => {
res.status(HttpStatus.OK).json({
status: HttpStatus.OK,
message: 'Welcome to the Evolution API, it is working!',
version: packageJson.version,
clientName: process.env.DATABASE_CONNECTION_CLIENT_NAME,
manager: !serverConfig.DISABLE_MANAGER ? `${req.protocol}://${req.get('host')}/manager` : undefined,
documentation: `https://doc.evolution-api.com`,
whatsappWebVersion: (await fetchLatestWaWebVersion({})).version.join('.'),
});
})
.use('/instance', new InstanceRouter(configService, ...guards).router)
.use('/message', new MessageRouter(...guards).router)
.use('/chat', new ChatRouter(...guards).router)
.use('/business', new BusinessRouter(...guards).router);
export { HttpStatus, router };
```
## Data Validation Pattern
### RouterBroker dataValidate Usage
```typescript
// CORRECT - Standard validation pattern
.post(this.routerPath('createTemplate'), ...guards, async (req, res) => {
const response = await this.dataValidate<TemplateDto>({
request: req,
schema: templateSchema,
ClassRef: TemplateDto,
execute: (instance, data) => templateController.create(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
// CORRECT - No schema validation (for simple DTOs)
.get(this.routerPath('findTemplate'), ...guards, async (req, res) => {
const response = await this.dataValidate<InstanceDto>({
request: req,
schema: null,
ClassRef: InstanceDto,
execute: (instance) => templateController.find(instance),
});
return res.status(HttpStatus.OK).json(response);
})
```
## Error Handling in Routes
### Try-Catch Pattern
```typescript
// CORRECT - Error handling with utility function
.post(this.routerPath('getCatalog'), ...guards, async (req, res) => {
try {
const response = await this.dataValidate<NumberDto>({
request: req,
schema: catalogSchema,
ClassRef: NumberDto,
execute: (instance, data) => businessController.fetchCatalog(instance, data),
});
return res.status(HttpStatus.OK).json(response);
} catch (error) {
// Log error for debugging
console.error('Business catalog error:', error);
// Use utility function to create standardized error response
const errorResponse = createMetaErrorResponse(error, 'business_catalog');
return res.status(errorResponse.status).json(errorResponse);
}
})
// INCORRECT - Let RouterBroker handle errors (when possible)
.post(this.routerPath('simpleOperation'), ...guards, async (req, res) => {
try {
const response = await this.dataValidate<SimpleDto>({
request: req,
schema: simpleSchema,
ClassRef: SimpleDto,
execute: (instance, data) => controller.simpleOperation(instance, data),
});
return res.status(HttpStatus.OK).json(response);
} catch (error) {
throw error; // ❌ Unnecessary - RouterBroker handles this
}
})
```
## Route Path Pattern
### routerPath Usage
```typescript
// CORRECT - Use routerPath for consistent naming
.get(this.routerPath('findLabels'), ...guards, async (req, res) => {
// Implementation
})
.post(this.routerPath('handleLabel'), ...guards, async (req, res) => {
// Implementation
})
// INCORRECT - Hardcoded paths
.get('/labels', ...guards, async (req, res) => { // ❌ Use routerPath
// Implementation
})
```
## Guard Application Pattern
### Guards Usage
```typescript
// CORRECT - Apply guards to protected routes
export class ProtectedRouter extends RouterBroker {
constructor(...guards: RequestHandler[]) {
super();
this.router
.get(this.routerPath('protectedAction'), ...guards, async (req, res) => {
// Protected action
})
.post(this.routerPath('anotherAction'), ...guards, async (req, res) => {
// Another protected action
});
}
}
// CORRECT - No guards for public routes
export class PublicRouter extends RouterBroker {
constructor() {
super();
this.router
.get('/health', async (req, res) => {
res.status(HttpStatus.OK).json({ status: 'healthy' });
})
.get('/version', async (req, res) => {
res.status(HttpStatus.OK).json({ version: packageJson.version });
});
}
}
```
## Static File Serving Pattern
### Static Assets Route
```typescript
// CORRECT - Secure static file serving
router.get('/assets/*', (req, res) => {
const fileName = req.params[0];
// Security: Reject paths containing traversal patterns
if (!fileName || fileName.includes('..') || fileName.includes('\\') || path.isAbsolute(fileName)) {
return res.status(403).send('Forbidden');
}
const basePath = path.join(process.cwd(), 'manager', 'dist');
const assetsPath = path.join(basePath, 'assets');
const filePath = path.join(assetsPath, fileName);
// Security: Ensure the resolved path is within the assets directory
const resolvedPath = path.resolve(filePath);
const resolvedAssetsPath = path.resolve(assetsPath);
if (!resolvedPath.startsWith(resolvedAssetsPath + path.sep) && resolvedPath !== resolvedAssetsPath) {
return res.status(403).send('Forbidden');
}
if (fs.existsSync(resolvedPath)) {
res.set('Content-Type', mimeTypes.lookup(resolvedPath) || 'text/css');
res.send(fs.readFileSync(resolvedPath));
} else {
res.status(404).send('File not found');
}
});
```
## Special Route Patterns
### Manager Route Pattern
```typescript
export class ViewsRouter extends RouterBroker {
public readonly router: Router;
constructor() {
super();
this.router = Router();
const basePath = path.join(process.cwd(), 'manager', 'dist');
const indexPath = path.join(basePath, 'index.html');
this.router.use(express.static(basePath));
this.router.get('*', (req, res) => {
res.sendFile(indexPath);
});
}
}
```
### Webhook Route Pattern
```typescript
// CORRECT - Webhook without guards
.post('/webhook/evolution', async (req, res) => {
const response = await evolutionController.receiveWebhook(req.body);
return res.status(HttpStatus.OK).json(response);
})
// CORRECT - Webhook with signature validation
.post('/webhook/meta', validateWebhookSignature, async (req, res) => {
const response = await metaController.receiveWebhook(req.body);
return res.status(HttpStatus.OK).json(response);
})
```
## Response Pattern
### Standard Response Format
```typescript
// CORRECT - Standard success response
return res.status(HttpStatus.OK).json(response);
// CORRECT - Created response
return res.status(HttpStatus.CREATED).json(response);
// CORRECT - Custom response with additional data
return res.status(HttpStatus.OK).json({
...response,
timestamp: new Date().toISOString(),
instanceName: req.params.instanceName,
});
```
## Route Organization
### File Structure
```
src/api/routes/
├── index.router.ts # Main router with all route registrations
├── instance.router.ts # Instance management routes
├── sendMessage.router.ts # Message sending routes
├── chat.router.ts # Chat operations routes
├── business.router.ts # Business API routes
├── group.router.ts # Group management routes
├── label.router.ts # Label management routes
├── proxy.router.ts # Proxy configuration routes
├── settings.router.ts # Instance settings routes
├── template.router.ts # Template management routes
├── call.router.ts # Call operations routes
└── view.router.ts # Frontend views routes
```
## Route Testing Pattern
### Router Testing
```typescript
describe('ExampleRouter', () => {
let app: express.Application;
let router: ExampleRouter;
beforeEach(() => {
app = express();
router = new ExampleRouter();
app.use('/api', router.router);
app.use(express.json());
});
describe('GET /findExample', () => {
it('should return example data', async () => {
const response = await request(app)
.get('/api/findExample/test-instance')
.set('apikey', 'test-key')
.expect(200);
expect(response.body).toBeDefined();
expect(response.body.instanceName).toBe('test-instance');
});
it('should return 401 without API key', async () => {
await request(app)
.get('/api/findExample/test-instance')
.expect(401);
});
});
describe('POST /createExample', () => {
it('should create example successfully', async () => {
const data = {
name: 'Test Example',
description: 'Test Description',
};
const response = await request(app)
.post('/api/createExample/test-instance')
.set('apikey', 'test-key')
.send(data)
.expect(201);
expect(response.body.name).toBe(data.name);
});
it('should validate required fields', async () => {
const data = {
description: 'Test Description',
// Missing required 'name' field
};
await request(app)
.post('/api/createExample/test-instance')
.set('apikey', 'test-key')
.send(data)
.expect(400);
});
});
});
```
## Route Documentation
### JSDoc for Routes
```typescript
/**
* @route GET /api/template/findTemplate/:instanceName
* @description Find template for instance
* @param {string} instanceName - Instance name
* @returns {TemplateDto} Template data
* @throws {404} Template not found
* @throws {401} Unauthorized
*/
.get(this.routerPath('findTemplate'), ...guards, async (req, res) => {
// Implementation
})
/**
* @route POST /api/template/createTemplate/:instanceName
* @description Create new template
* @param {string} instanceName - Instance name
* @body {TemplateDto} Template data
* @returns {TemplateDto} Created template
* @throws {400} Validation error
* @throws {401} Unauthorized
*/
.post(this.routerPath('createTemplate'), ...guards, async (req, res) => {
// Implementation
})
```
================================================
FILE: .cursor/rules/specialized-rules/service-rules.mdc
================================================
---
description: Service layer patterns for Evolution API
globs:
- "src/api/services/**/*.ts"
- "src/api/integrations/**/services/*.ts"
alwaysApply: false
---
# Evolution API Service Rules
## Service Structure Pattern
### Standard Service Class
```typescript
export class ExampleService {
constructor(private readonly waMonitor: WAMonitoringService) {}
private readonly logger = new Logger('ExampleService');
public async create(instance: InstanceDto, data: ExampleDto) {
await this.waMonitor.waInstances[instance.instanceName].setData(data);
return { example: { ...instance, data } };
}
public async find(instance: InstanceDto): Promise<ExampleDto> {
try {
const result = await this.waMonitor.waInstances[instance.instanceName].findData();
if (Object.keys(result).length === 0) {
throw new Error('Data not found');
}
return result;
} catch (error) {
return null; // Evolution pattern - return null on error
}
}
}
```
## Dependency Injection Pattern
### Constructor Pattern
```typescript
// CORRECT - Evolution API pattern
constructor(
private readonly waMonitor: WAMonitoringService,
private readonly prismaRepository: PrismaRepository,
private readonly configService: ConfigService,
) {}
// INCORRECT - Don't use
constructor(waMonitor, prismaRepository, configService) {} // ❌ No types
```
## Logger Pattern
### Standard Logger Usage
```typescript
// CORRECT - Evolution API pattern
private readonly logger = new Logger('ServiceName');
// Usage
this.logger.log('Operation started');
this.logger.error('Operation failed', error);
// INCORRECT
console.log('Operation started'); // ❌ Use Logger
```
## WAMonitor Integration Pattern
### Instance Access Pattern
```typescript
// CORRECT - Standard pattern
public async operation(instance: InstanceDto, data: DataDto) {
await this.waMonitor.waInstances[instance.instanceName].performAction(data);
return { result: { ...instance, data } };
}
// Instance validation
const waInstance = this.waMonitor.waInstances[instance.instanceName];
if (!waInstance) {
throw new NotFoundException('Instance not found');
}
```
## Error Handling Pattern
### Try-Catch Pattern
```typescript
// CORRECT - Evolution API pattern
public async find(instance: InstanceDto): Promise<DataDto> {
try {
const result = await this.waMonitor.waInstances[instance.instanceName].findData();
if (Object.keys(result).length === 0) {
throw new Error('Data not found');
}
return result;
} catch (error) {
this.logger.error('Find operation failed', error);
return null; // Return null on error (Evolution pattern)
}
}
```
## Cache Integration Pattern
### Cache Service Usage
```typescript
export class CacheAwareService {
constructor(
private readonly cache: CacheService,
private readonly chatwootCache: CacheService,
private readonly baileysCache: CacheService,
) {}
public async getCachedData(key: string): Promise<any> {
const cached = await this.cache.get(key);
if (cached) return cached;
const data = await this.fetchFromSource(key);
await this.cache.set(key, data, 300); // 5 min TTL
return data;
}
}
```
## Integration Service Patterns
### Chatbot Service Base Pattern
```typescript
export class ChatbotService extends BaseChatbotService<BotType, SettingsType> {
constructor(
waMonitor: WAMonitoringService,
prismaRepository: PrismaRepository,
configService: ConfigService,
) {
super(waMonitor, prismaRepository, 'ChatbotService', configService);
}
protected async processBot(
waInstance: any,
remoteJid: string,
bot: BotType,
session: any,
settings: any,
content: string,
): Promise<void> {
// Implementation
}
}
```
### Channel Service Pattern
```typescript
export class ChannelService extends ChannelStartupService {
constructor(
configService: ConfigService,
eventEmitter: EventEmitter2,
prismaRepository: PrismaRepository,
cache: CacheService,
chatwootCache: CacheService,
baileysCache: CacheService,
) {
super(configService, eventEmitter, prismaRepository, cache, chatwootCache, baileysCache);
}
public readonly logger = new Logger('ChannelService');
public client: WASocket;
public readonly instance: wa.Instance = {};
}
```
## Service Initialization Pattern
### Service Registration
```typescript
// In server.module.ts pattern
export const templateService = new TemplateService(
waMonitor,
prismaRepository,
configService,
);
export const settingsService = new SettingsService(waMonitor);
```
## Async Operation Patterns
### Promise Handling
```typescript
// CORRECT - Evolution API pattern
public async sendMessage(instance: InstanceDto, data: MessageDto) {
const waInstance = this.waMonitor.waInstances[instance.instanceName];
return await waInstance.sendMessage(data);
}
// INCORRECT - Don't use .then()
public sendMessage(instance: InstanceDto, data: MessageDto) {
return this.waMonitor.waInstances[instance.instanceName]
.sendMessage(data)
.then(result => result); // ❌ Use async/await
}
```
## Configuration Access Pattern
### Config Service Usage
```typescript
// CORRECT - Evolution API pattern
const serverConfig = this.configService.get<HttpServer>('SERVER');
const authConfig = this.configService.get<Auth>('AUTHENTICATION');
const dbConfig = this.configService.get<Database>('DATABASE');
// Type-safe configuration access
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED) {
// Chatwoot logic
}
```
## Event Emission Pattern
### EventEmitter2 Usage
```typescript
// CORRECT - Evolution API pattern
this.eventEmitter.emit(Events.INSTANCE_CREATE, {
instanceName: instance.name,
status: 'created',
});
// Chatwoot event pattern
if (this.configService.get<Chatwoot>('CHATWOOT').ENABLED && this.localChatwoot?.enabled) {
this.chatwootService.eventWhatsapp(
Events.STATUS_INSTANCE,
{ instanceName: this.instance.name },
{
instance: this.instance.name,
status: 'created',
},
);
}
```
## Service Method Naming
### Standard Method Names
- `create()` - Create new resource
- `find()` - Find single resource
- `findAll()` - Find multiple resources
- `update()` - Update resource
- `delete()` - Delete resource
- `fetch*()` - Fetch from external API
- `send*()` - Send data/messages
- `process*()` - Process data
## Service Testing Pattern
### Unit Test Structure
```typescript
describe('ExampleService', () => {
let service: ExampleService;
let waMonitor: jest.Mocked<WAMonitoringService>;
let prismaRepository: jest.Mocked<PrismaRepository>;
beforeEach(() => {
const mockWaMonitor = {
waInstances: {
'test-instance': {
performAction: jest.fn(),
},
},
};
service = new ExampleService(
mockWaMonitor as any,
prismaRepository,
configService,
);
});
it('should perform action successfully', async () => {
const instance = { instanceName: 'test-instance' };
const data = { test: 'data' };
const result = await service.create(instance, data);
expect(result).toBeDefined();
expect(waMonitor.waInstances['test-instance'].performAction).toHaveBeenCalledWith(data);
});
});
```
================================================
FILE: .cursor/rules/specialized-rules/type-rules.mdc
================================================
---
description: Type definitions and interfaces for Evolution API
globs:
- "src/api/types/**/*.ts"
- "src/@types/**/*.ts"
alwaysApply: false
---
# Evolution API Type Rules
## Namespace Pattern
### WhatsApp Types Namespace
```typescript
/* eslint-disable @typescript-eslint/no-namespace */
import { JsonValue } from '@prisma/client/runtime/library';
import { AuthenticationState, WAConnectionState } from 'baileys';
export declare namespace wa {
export type QrCode = {
count?: number;
pairingCode?: string;
base64?: string;
code?: string;
};
export type Instance = {
id?: string;
qrcode?: QrCode;
pairingCode?: string;
authState?: { state: AuthenticationState; saveCreds: () => void };
name?: string;
wuid?: string;
profileName?: string;
profilePictureUrl?: string;
token?: string;
number?: string;
integration?: string;
businessId?: string;
};
export type LocalChatwoot = {
enabled?: boolean;
accountId?: string;
token?: string;
url?: string;
nameInbox?: string;
mergeBrazilContacts?: boolean;
importContacts?: boolean;
importMessages?: boolean;
daysLimitImportMessages?: number;
organization?: string;
logo?: string;
};
export type LocalProxy = {
enabled?: boolean;
host?: string;
port?: string;
protocol?: string;
username?: string;
password?: string;
};
export type LocalSettings = {
rejectCall?: boolean;
msgCall?: string;
groupsIgnore?: boolean;
alwaysOnline?: boolean;
readMessages?: boolean;
readStatus?: boolean;
syncFullHistory?: boolean;
};
export type LocalWebHook = {
enabled?: boolean;
url?: string;
events?: string[];
headers?: JsonValue;
byEvents?: boolean;
base64?: boolean;
};
export type StatusMessage = 'ERROR' | 'PENDING' | 'SERVER_ACK' | 'DELIVERY_ACK' | 'READ' | 'DELETED' | 'PLAYED';
}
```
## Enum Definitions
### Events Enum
```typescript
export enum Events {
APPLICATION_STARTUP = 'application.startup',
INSTANCE_CREATE = 'instance.create',
INSTANCE_DELETE = 'instance.delete',
QRCODE_UPDATED = 'qrcode.updated',
CONNECTION_UPDATE = 'connection.update',
STATUS_INSTANCE = 'status.instance',
MESSAGES_SET = 'messages.set',
MESSAGES_UPSERT = 'messages.upsert',
MESSAGES_EDITED = 'messages.edited',
MESSAGES_UPDATE = 'messages.update',
MESSAGES_DELETE = 'messages.delete',
SEND_MESSAGE = 'send.message',
SEND_MESSAGE_UPDATE = 'send.message.update',
CONTACTS_SET = 'contacts.set',
CONTACTS_UPSERT = 'contacts.upsert',
CONTACTS_UPDATE = 'contacts.update',
PRESENCE_UPDATE = 'presence.update',
CHATS_SET = 'chats.set',
CHATS_UPDATE = 'chats.update',
CHATS_UPSERT = 'chats.upsert',
CHATS_DELETE = 'chats.delete',
GROUPS_UPSERT = 'groups.upsert',
GROUPS_UPDATE = 'groups.update',
GROUP_PARTICIPANTS_UPDATE = 'group-participants.update',
CALL = 'call',
TYPEBOT_START = 'typebot.start',
TYPEBOT_CHANGE_STATUS = 'typebot.change-status',
LABELS_EDIT = 'labels.edit',
LABELS_ASSOCIATION = 'labels.association',
CREDS_UPDATE = 'creds.update',
MESSAGING_HISTORY_SET = 'messaging-history.set',
REMOVE_INSTANCE = 'remove.instance',
LOGOUT_INSTANCE = 'logout.instance',
}
```
### Integration Types
```typescript
export const Integration = {
WHATSAPP_BUSINESS: 'WHATSAPP-BUSINESS',
WHATSAPP_BAILEYS: 'WHATSAPP-BAILEYS',
EVOLUTION: 'EVOLUTION',
} as const;
export type IntegrationType = typeof Integration[keyof typeof Integration];
```
## Constant Arrays
### Message Type Constants
```typescript
export const TypeMediaMessage = [
'imageMessage',
'documentMessage',
'audioMessage',
'videoMessage',
'stickerMessage',
'ptvMessage', // Evolution API includes this
];
export const MessageSubtype = [
'ephemeralMessage',
'documentWithCaptionMessage',
'viewOnceMessage',
'viewOnceMessageV2',
];
export type MediaMessageType = typeof TypeMediaMessage[number];
export type MessageSubtypeType = typeof MessageSubtype[number];
```
## Interface Definitions
### Service Interfaces
```typescript
export interface ServiceInterface {
create(instance: InstanceDto, data: any): Promise<any>;
find(instance: InstanceDto): Promise<any>;
update?(instance: InstanceDto, data: any): Promise<any>;
delete?(instance: InstanceDto): Promise<any>;
}
export interface ChannelServiceInterface extends ServiceInterface {
sendMessage(data: SendMessageDto): Promise<any>;
connectToWhatsapp(data?: any): Promise<void>;
receiveWebhook?(data: any): Promise<void>;
}
export interface ChatbotServiceInterface extends ServiceInterface {
processMessage(
instanceName: string,
remoteJid: string,
message: any,
pushName?: string,
): Promise<void>;
}
```
## Configuration Types
### Environment Configuration Types
```typescript
export interface DatabaseConfig {
CONNECTION: {
URI: string;
DB_PREFIX_NAME: string;
CLIENT_NAME?: string;
};
ENABLED: boolean;
SAVE_DATA: {
INSTANCE: boolean;
NEW_MESSAGE: boolean;
MESSAGE_UPDATE: boolean;
CONTACTS: boolean;
CHATS: boolean;
};
}
export interface AuthConfig {
TYPE: 'apikey' | 'jwt';
API_KEY: {
KEY: string;
};
JWT?: {
EXPIRIN_IN: number;
SECRET: string;
};
}
export interface CacheConfig {
REDIS: {
ENABLED: boolean;
URI: string;
PREFIX_KEY: string;
SAVE_INSTANCES: boolean;
};
LOCAL: {
ENABLED: boolean;
TTL: number;
};
}
```
## Message Types
### Message Structure Types
```typescript
export interface MessageContent {
text?: string;
caption?: string;
media?: Buffer | string;
mediatype?: 'image' | 'video' | 'audio' | 'document' | 'sticker';
fileName?: string;
mimetype?: string;
}
export interface MessageOptions {
delay?: number;
presence?: 'unavailable' | 'available' | 'composing' | 'recording' | 'paused';
linkPreview?: boolean;
mentionsEveryOne?: boolean;
mentioned?: string[];
quoted?: {
key: {
remoteJid: string;
fromMe: boolean;
id: string;
};
message: any;
};
}
export interface SendMessageRequest {
number: string;
content: MessageContent;
options?: MessageOptions;
}
```
## Webhook Types
### Webhook Payload Types
```typescript
export interface WebhookPayload {
event: Events;
instance: string;
data: any;
timestamp: string;
server?: {
version: string;
host: string;
};
}
export interface WebhookConfig {
enabled: boolean;
url: string;
events: Events[];
headers?: Record<string, string>;
byEvents?: boolean;
base64?: boolean;
}
```
## Error Types
### Custom Error Types
```typescript
export interface ApiError {
status: number;
message: string;
error?: string;
details?: any;
timestamp: string;
path: string;
}
export interface ValidationError extends ApiError {
status: 400;
validationErrors: Array<{
field: string;
message: string;
value?: any;
}>;
}
export interface AuthenticationError extends ApiError {
status: 401;
message: 'Unauthorized' | 'Invalid API Key' | 'Token Expired';
}
```
## Utility Types
### Generic Utility Types
```typescript
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
export type RequiredFields<T, K extends keyof T> = T & Required<Pick<T, K>>;
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
export type NonEmptyArray<T> = [T, ...T[]];
export type StringKeys<T> = {
[K in keyof T]: T[K] extends string ? K : never;
}[keyof T];
```
## Response Types
### API Response Types
```typescript
export interface ApiResponse<T = any> {
success: boolean;
data?: T;
message?: string;
error?: string;
timestamp: string;
}
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
hasNext: boolean;
hasPrev: boolean;
};
}
export interface InstanceResponse extends ApiResponse {
instance: {
instanceName: string;
status: 'connecting' | 'open' | 'close' | 'qr';
qrcode?: string;
profileName?: string;
profilePicUrl?: string;
};
}
```
## Integration-Specific Types
### Baileys Types Extension
```typescript
import { WASocket, ConnectionState, DisconnectReason } from 'baileys';
export interface BaileysInstance {
client: WASocket;
state: ConnectionState;
qrRetry: number;
authPath: string;
}
export interface BaileysConfig {
qrTimeout: number;
maxQrRetries: number;
authTimeout: number;
reconnectInterval: number;
}
```
### Business API Types
```typescript
export interface BusinessApiConfig {
version: string;
baseUrl: string;
timeout: number;
retries: number;
}
export interface BusinessApiMessage {
messaging_product: 'whatsapp';
to: string;
type: 'text' | 'image' | 'document' | 'audio' | 'video' | 'template';
text?: {
body: string;
preview_url?: boolean;
};
image?: {
link?: string;
id?: string;
caption?: string;
};
template?: {
name: string;
language: {
code: string;
};
components?: any[];
};
}
```
## Type Guards
### Type Guard Functions
```typescript
export function isMediaMessage(message: any): message is MediaMessage {
return message && TypeMediaMessage.some(type => message[type]);
}
export function isTextMessage(message: any): message is TextMessage {
return message && message.conversation;
}
export function isValidIntegration(integration: string): integration is IntegrationType {
return Object.values(Integration).includes(integration as IntegrationType);
}
export function isValidEvent(event: string): event is Events {
return Object.values(Events).includes(event as Events);
}
```
## Module Augmentation
### Express Request Extension
```typescript
declare global {
namespace Express {
interface Request {
instanceName?: string;
instanceData?: InstanceDto;
user?: {
id: string;
apiKey: string;
};
}
}
}
```
## Type Documentation
### JSDoc Type Documentation
```typescript
/**
* WhatsApp instance configuration
* @interface InstanceConfig
* @property {string} name - Unique instance name
* @property {IntegrationType} integration - Integration type
* @property {string} [token] - API token for business integrations
* @property {WebhookConfig} [webhook] - Webhook configuration
* @property {ProxyConfig} [proxy] - Proxy configuration
*/
export interface InstanceConfig {
name: string;
integration: IntegrationType;
token?: string;
webhook?: WebhookConfig;
proxy?: ProxyConfig;
}
```
================================================
FILE: .cursor/rules/specialized-rules/util-rules.mdc
================================================
---
description: Utility functions and helpers for Evolution API
globs:
- "src/utils/**/*.ts"
alwaysApply: false
---
# Evolution API Utility Rules
## Utility Function Structure
### Standard Utility Pattern
```typescript
import { Logger } from '@config/logger.config';
const logger = new Logger('UtilityName');
export function utilityFunction(param: ParamType): ReturnType {
try {
// Utility logic
return result;
} catch (error) {
logger.error(`Utility function failed: ${error.message}`);
throw error;
}
}
export default utilityFunction;
```
## Authentication Utilities
### Multi-File Auth State Pattern
```typescript
import { AuthenticationState } from 'baileys';
import { CacheService } from '@api/services/cache.service';
import fs from 'fs/promises';
import path from 'path';
export default async function useMultiFileAuthStatePrisma(
sessionId: string,
cache: CacheService,
): Promise<{
state: AuthenticationState;
saveCreds: () => Promise<void>;
}> {
const localFolder = path.join(INSTANCE_DIR, sessionId);
const localFile = (key: string) => path.join(localFolder, fixFileName(key) + '.json');
await fs.mkdir(localFolder, { recursive: true });
async function writeData(data: any, key: string): Promise<any> {
const dataString = JSON.stringify(data, BufferJSON.replacer);
if (key !== 'creds') {
if (process.env.CACHE_REDIS_ENABLED === 'true') {
return await cache.hSet(sessionId, key, data);
} else {
await fs.writeFile(localFile(key), dataString);
return;
}
}
await saveKey(sessionId, dataString);
return;
}
async function readData(key: string): Promise<any> {
try {
let rawData;
if (key !== 'creds') {
if (process.env.CACHE_REDIS_ENABLED === 'true') {
return await cache.hGet(sessionId, key);
} else {
if (!(await fileExists(localFile(key)))) return null;
rawData = await fs.readFile(localFile(key), { encoding: 'utf-8' });
return JSON.parse(rawData, BufferJSON.reviver);
}
} else {
rawData = await getAuthKey(sessionId);
}
const parsedData = JSON.parse(rawData, BufferJSON.reviver);
return parsedData;
} catch (error) {
return null;
}
}
async function removeData(key: string): Promise<any> {
try {
if (key !== 'creds') {
if (process.env.CACHE_REDIS_ENABLED === 'true') {
return await cache.hDelete(sessionId, key);
} else {
await fs.unlink(localFile(key));
}
} else {
await deleteAuthKey(sessionId);
}
} catch (error) {
return;
}
}
let creds = await readData('creds');
if (!creds) {
creds = initAuthCreds();
await writeData(creds, 'creds');
}
return {
state: {
creds,
keys: {
get: async (type, ids) => {
const data = {};
await Promise.all(
ids.map(async (id) => {
let value = await readData(`${type}-${id}`);
if (type === 'app-state-sync-key' && value) {
value = proto.Message.AppStateSyncKeyData.fromObject(value);
}
data[id] = value;
})
);
return data;
},
set: async (data) => {
const tasks = [];
for (const category in data) {
for (const id in data[category]) {
const value = data[category][id];
const key = `${category}-${id}`;
tasks.push(value ? writeData(value, key) : removeData(key));
}
}
await Promise.all(tasks);
},
},
},
saveCreds: () => writeData(creds, 'creds'),
};
}
```
## Message Processing Utilities
### Message Content Extraction
```typescript
export const getConversationMessage = (msg: any): string => {
const types = getTypeMessage(msg);
const messageContent = getMessageContent(types);
return messageContent;
};
const getTypeMessage = (msg: any): any => {
return Object.keys(msg?.message || msg || {})[0];
};
const getMessageContent = (type: string, msg?: any): string => {
const typeKey = type?.replace('Message', '');
const types = {
conversation: msg?.message?.conversation,
extendedTextMessage: msg?.message?.extendedTextMessage?.text,
imageMessage: msg?.message?.imageMessage?.caption || 'Image',
videoMessage: msg?.message?.videoMessage?.caption || 'Video',
audioMessage: 'Audio',
documentMessage: msg?.message?.documentMessage?.caption || 'Document',
stickerMessage: 'Sticker',
contactMessage: 'Contact',
locationMessage: 'Location',
liveLocationMessage: 'Live Location',
viewOnceMessage: 'View Once',
reactionMessage: 'Reaction',
pollCreationMessage: 'Poll',
pollUpdateMessage: 'Poll Update',
};
let result = types[typeKey] || types[type] || 'Unknown';
if (!result || result === 'Unknown') {
result = JSON.stringify(msg);
}
return result;
};
```
### JID Creation Utility
```typescript
export const createJid = (number: string): string => {
if (number.includes('@')) {
return number;
}
// Remove any non-numeric characters except +
let cleanNumber = number.replace(/[^\d+]/g, '');
// Remove + if present
if (cleanNumber.startsWith('+')) {
cleanNumber = cleanNumber.substring(1);
}
// Add country code if missing (assuming Brazil as default)
if (cleanNumber.length === 11 && cleanNumber.startsWith('11')) {
cleanNumber = '55' + cleanNumber;
} else if (cleanNumber.length === 10) {
cleanNumber = '5511' + cleanNumber;
}
// Determine if it's a group or individual
const isGroup = cleanNumber.includes('-');
const domain = isGroup ? 'g.us' : 's.whatsapp.net';
return `${cleanNumber}@${domain}`;
};
```
## Cache Utilities
### WhatsApp Number Cache
```typescript
interface ISaveOnWhatsappCacheParams {
remoteJid: string;
lid?: string;
}
function getAvailableNumbers(remoteJid: string): string[] {
const numbersAvailable: string[] = [];
if (remoteJid.startsWith('+')) {
remoteJid = remoteJid.slice(1);
}
const [number, domain] = remoteJid.split('@');
// Brazilian numbers
if (remoteJid.startsWith('55')) {
const numberWithDigit =
number.slice(4, 5) === '9' && number.length === 13 ? number : `${number.slice(0, 4)}9${number.slice(4)}`;
const numberWithoutDigit = number.length === 12 ? number : number.slice(0, 4) + number.slice(5);
numbersAvailable.push(numberWithDigit);
numbersAvailable.push(numberWithoutDigit);
}
// Mexican/Argentina numbers
else if (number.startsWith('52') || number.startsWith('54')) {
let prefix = '';
if (number.startsWith('52')) {
prefix = '1';
}
if (number.startsWith('54')) {
prefix = '9';
}
const numberWithDigit =
number.slice(2, 3) === prefix && number.length === 13
? number
: `${number.slice(0, 2)}${prefix}${number.slice(2)}`;
const numberWithoutDigit = number.length === 12 ? number : number.slice(0, 2) + number.slice(3);
numbersAvailable.push(numberWithDigit);
numbersAvailable.push(numberWithoutDigit);
}
// Other countries
else {
numbersAvailable.push(remoteJid);
}
return numbersAvailable.map((number) => `${number}@${domain}`);
}
export async function saveOnWhatsappCache(params: ISaveOnWhatsappCacheParams): Promise<void> {
const { remoteJid, lid } = params;
const db = configService.get<Database>('DATABASE');
if (!db.SAVE_DATA.CONTACTS) {
return;
}
try {
const numbersAvailable = getAvailableNumbers(remoteJid);
const existingContact = await prismaRepository.contact.findFirst({
where: {
OR: numbersAvailable.map(number => ({ id: number })),
},
});
if (!existingContact) {
await prismaRepository.contact.create({
data: {
id: remoteJid,
pushName: '',
profilePicUrl: '',
isOnWhatsapp: true,
lid: lid || null,
createdAt: new Date(),
updatedAt: new Date(),
},
});
} else {
await prismaRepository.contact.update({
where: { id: existingContact.id },
data: {
isOnWhatsapp: true,
lid: lid || existingContact.lid,
updatedAt: new Date(),
},
});
}
} catch (error) {
console.error('Error saving WhatsApp cache:', error);
}
}
```
## Search Utilities
### Advanced Search Operators
```typescript
function normalizeString(str: string): string {
return str
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '');
}
export function advancedOperatorsSearch(data: string, query: string): boolean {
const normalizedData = normalizeString(data);
const normalizedQuery = normalizeString(query);
// Exact phrase search with quotes
if (normalizedQuery.startsWith('"') && normalizedQuery.endsWith('"')) {
const phrase = normalizedQuery.slice(1, -1);
return normalizedData.includes(phrase);
}
// OR operator
if (normalizedQuery.includes(' OR ')) {
const terms = normalizedQuery.split(' OR ');
return terms.some(term => normalizedData.includes(term.trim()));
}
// AND operator (default behavior)
if (normalizedQuery.includes(' AND ')) {
const terms = normalizedQuery.split(' AND ');
return terms.every(term => normalizedData.includes(term.trim()));
}
// NOT operator
if (normalizedQuery.startsWith('NOT ')) {
const term = normalizedQuery.slice(4);
return !normalizedData.includes(term);
}
// Wildcard search
if (normalizedQuery.includes('*')) {
const regex = new RegExp(normalizedQuery.replace(/\*/g, '.*'), 'i');
return regex.test(normalizedData);
}
// Default: simple contains search
return normalizedData.includes(normalizedQuery);
}
```
## Proxy Utilities
### Proxy Agent Creation
```typescript
import { HttpsProxyAgent } from 'https-proxy-agent';
import { SocksProxyAgent } from 'socks-proxy-agent';
type Proxy = {
host: string;
port: string;
protocol: 'http' | 'https' | 'socks4' | 'socks5';
username?: string;
password?: string;
};
function selectProxyAgent(proxyUrl: string): HttpsProxyAgent<string> | SocksProxyAgent {
const url = new URL(proxyUrl);
if (url.protocol === 'socks4:' || url.protocol === 'socks5:') {
return new SocksProxyAgent(proxyUrl);
} else {
return new HttpsProxyAgent(proxyUrl);
}
}
export function makeProxyAgent(proxy: Proxy): HttpsProxyAgent<string> | SocksProxyAgent | null {
if (!proxy.host || !proxy.port) {
return null;
}
let proxyUrl = `${proxy.protocol}://`;
if (proxy.username && proxy.password) {
proxyUrl += `${proxy.username}:${proxy.password}@`;
}
proxyUrl += `${proxy.host}:${proxy.port}`;
try {
return selectProxyAgent(proxyUrl);
} catch (error) {
console.error('Failed to create proxy agent:', error);
return null;
}
}
```
## Telemetry Utilities
### Telemetry Data Collection
```typescript
export interface TelemetryData {
route: string;
apiVersion: string;
timestamp: Date;
method?: string;
statusCode?: number;
responseTime?: number;
userAgent?: string;
instanceName?: string;
}
export const sendTelemetry = async (route: string): Promise<void> => {
try {
const telemetryData: TelemetryData = {
route,
apiVersion: packageJson.version,
timestamp: new Date(),
};
// Only send telemetry if enabled
if (process.env.DISABLE_TELEMETRY === 'true') {
return;
}
// Send to telemetry service (implement as needed)
await axios.post('https://telemetry.evolution-api.com/collect', telemetryData, {
timeout: 5000,
});
} catch (error) {
// Silently fail - don't affect main application
console.debug('Telemetry failed:', error.message);
}
};
```
## Internationalization Utilities
### i18n Setup
```typescript
import { ConfigService, Language } from '@config/env.config';
import fs from 'fs';
import i18next from 'i18next';
import path from 'path';
const __dirname = path.resolve(process.cwd(), 'src', 'utils');
const languages = ['en', 'pt-BR', 'es'];
const translationsPath = path.join(__dirname, 'translations');
const configService: ConfigService = new ConfigService();
const resources: any = {};
languages.forEach((language) => {
const languagePath = path.join(translationsPath, `${language}.json`);
if (fs.existsSync(languagePath)) {
const translationContent = fs.readFileSync(languagePath, 'utf8');
resources[language] = {
translation: JSON.parse(translationContent),
};
}
});
i18next.init({
resources,
fallbackLng: 'en',
lng: configService.get<Language>('LANGUAGE') || 'pt-BR',
interpolation: {
escapeValue: false,
},
});
export const t = i18next.t.bind(i18next);
export default i18next;
```
## Bot Trigger Utilities
### Bot Trigger Matching
```typescript
import { TriggerOperator, TriggerType } from '@prisma/client';
export function findBotByTrigger(
bots: any[],
content: string,
remoteJid: string,
): any | null {
for (const bot of bots) {
if (!bot.enabled) continue;
// Check ignore list
if (bot.ignoreJids && bot.ignoreJids.includes(remoteJid)) {
continue;
}
// Check trigger
if (matchesTrigger(content, bot.triggerType, bot.triggerOperator, bot.triggerValue)) {
return bot;
}
}
return null;
}
function matchesTrigger(
content: string,
triggerType: TriggerType,
triggerOperator: TriggerOperator,
triggerValue: string,
): boolean {
const normalizedContent = content.toLowerCase().trim();
const normalizedValue = triggerValue.toLowerCase().trim();
switch (triggerType) {
case TriggerType.ALL:
return true;
case TriggerType.KEYWORD:
return matchesKeyword(normalizedContent, triggerOperator, normalizedValue);
case TriggerType.REGEX:
try {
const regex = new RegExp(triggerValue, 'i');
return regex.test(content);
} catch {
return false;
}
default:
return false;
}
}
function matchesKeyword(
content: string,
operator: TriggerOperator,
value: string,
): boolean {
switch (operator) {
case TriggerOperator.EQUALS:
return content === value;
case TriggerOperator.CONTAINS:
return content.includes(value);
case TriggerOperator.STARTS_WITH:
return content.startsWith(value);
case TriggerOperator.ENDS_WITH:
return content.endsWith(value);
default:
return false;
}
}
```
## Server Utilities
### Server Status Check
```typescript
export class ServerUP {
private static instance: ServerUP;
private isServerUp: boolean = false;
private constructor() {}
public static getInstance(): ServerUP {
if (!ServerUP.instance) {
ServerUP.instance = new ServerUP();
}
return ServerUP.instance;
}
public setServerStatus(status: boolean): void {
this.isServerUp = status;
}
public getServerStatus(): boolean {
return this.isServerUp;
}
public async waitForServer(timeout: number = 30000): Promise<boolean> {
const startTime = Date.now();
while (!this.isServerUp && (Date.now() - startTime) < timeout) {
await new Promise(resolve => setTimeout(resolve, 100));
}
return this.isServerUp;
}
}
```
## Error Response Utilities
### Standardized Error Responses
```typescript
export function createMetaErrorResponse(error: any, context: string) {
const timestamp = new Date().toISOString();
if (error.response?.data) {
return {
status: error.response.status || 500,
error: {
message: error.response.data.error?.message || 'External API error',
type: error.response.data.error?.type || 'api_error',
code: error.response.data.error?.code || 'unknown_error',
context,
timestamp,
},
};
}
return {
status: 500,
error: {
message: error.message || 'Internal server error',
type: 'internal_error',
code: 'server_error',
context,
timestamp,
},
};
}
export function createValidationErrorResponse(errors: any[], context: string) {
return {
status: 400,
error: {
message: 'Validation failed',
type: 'validation_error',
code: 'invalid_input',
context,
details: errors,
timestamp: new Date().toISOString(),
},
};
}
```
================================================
FILE: .cursor/rules/specialized-rules/validate-rules.mdc
================================================
---
description: Validation schemas and patterns for Evolution API
globs:
- "src/validate/**/*.ts"
alwaysApply: false
---
# Evolution API Validation Rules
## Validation Schema Structure
### JSONSchema7 Pattern (Evolution API Standard)
```typescript
import { JSONSchema7 } from 'json-schema';
import { v4 } from 'uuid';
const isNotEmpty = (...fields: string[]) => {
const properties = {};
fields.forEach((field) => {
properties[field] = {
if: { properties: { [field]: { type: 'string' } } },
then: { properties: { [field]: { minLength: 1 } } },
};
});
return {
allOf: Object.values(properties),
};
};
export const exampleSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
name: { type: 'string' },
description: { type: 'string' },
enabled: { type: 'boolean' },
settings: {
type: 'object',
properties: {
timeout: { type: 'number', minimum: 1000, maximum: 60000 },
retries: { type: 'number', minimum: 0, maximum: 5 },
},
},
tags: {
type: 'array',
items: { type: 'string' },
},
},
required: ['name', 'enabled'],
...isNotEmpty('name'),
};
```
## Message Validation Schemas
### Send Message Validation
```typescript
const numberDefinition = {
type: 'string',
pattern: '^\\d+[\\.@\\w-]+',
description: 'Invalid number',
};
export const sendTextSchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
number: numberDefinition,
text: { type: 'string', minLength: 1, maxLength: 4096 },
delay: { type: 'number', minimum: 0, maximum: 60000 },
linkPreview: { type: 'boolean' },
mentionsEveryOne: { type: 'boolean' },
mentioned: {
type: 'array',
items: { type: 'string' },
},
},
required: ['number', 'text'],
...isNotEmpty('number', 'text'),
};
export const sendMediaSchema = Joi.object({
number: Joi.string().required().pattern(/^\d+$/),
mediatype: Joi.string().required().valid('image', 'video', 'audio', 'document'),
media: Joi.alternatives().try(
Joi.string().uri(),
Joi.string().base64(),
).required(),
caption: Joi.string().optional().max(1024),
fileName: Joi.string().optional().max(255),
delay: Joi.number().optional().min(0).max(60000),
}).required();
export const sendButtonsSchema = Joi.object({
number: Joi.string().required().pattern(/^\d+$/),
title: Joi.string().required().max(1024),
description: Joi.string().optional().max(1024),
footer: Joi.string().optional().max(60),
buttons: Joi.array().items(
Joi.object({
type: Joi.string().required().valid('replyButton', 'urlButton', 'callButton'),
displayText: Joi.string().required().max(20),
id: Joi.string().when('type', {
is: 'replyButton',
then: Joi.required().max(256),
otherwise: Joi.optional(),
}),
url: Joi.string().when('type', {
is: 'urlButton',
then: Joi.required().uri(),
otherwise: Joi.optional(),
}),
phoneNumber: Joi.string().when('type', {
is: 'callButton',
then: Joi.required().pattern(/^\+?\d+$/),
otherwise: Joi.optional(),
}),
})
).min(1).max(3).required(),
}).required();
```
## Instance Validation Schemas
### Instance Creation Validation
```typescript
export const instanceSchema = Joi.object({
instanceName: Joi.string().required().min(1).max(100).pattern(/^[a-zA-Z0-9_-]+$/),
integration: Joi.string().required().valid('WHATSAPP-BAILEYS', 'WHATSAPP-BUSINESS', 'EVOLUTION'),
token: Joi.string().when('integration', {
is: Joi.valid('WHATSAPP-BUSINESS', 'EVOLUTION'),
then: Joi.required().min(10),
otherwise: Joi.optional(),
}),
qrcode: Joi.boolean().optional().default(false),
number: Joi.string().optional().pattern(/^\d+$/),
businessId: Joi.string().when('integration', {
is: 'WHATSAPP-BUSINESS',
then: Joi.required(),
otherwise: Joi.optional(),
}),
}).required();
export const settingsSchema = Joi.object({
rejectCall: Joi.boolean().optional(),
msgCall: Joi.string().optional().max(500),
groupsIgnore: Joi.boolean().optional(),
alwaysOnline: Joi.boolean().optional(),
readMessages: Joi.boolean().optional(),
readStatus: Joi.boolean().optional(),
syncFullHistory: Joi.boolean().optional(),
wavoipToken: Joi.string().optional(),
}).optional();
export const proxySchema = Joi.object({
host: Joi.string().required().hostname(),
port: Joi.string().required().pattern(/^\d+$/).custom((value) => {
const port = parseInt(value);
if (port < 1 || port > 65535) {
throw new Error('Port must be between 1 and 65535');
}
return value;
}),
protocol: Joi.string().required().valid('http', 'https', 'socks4', 'socks5'),
username: Joi.string().optional(),
password: Joi.string().optional(),
}).optional();
```
## Webhook Validation Schemas
### Webhook Configuration Validation
```typescript
export const webhookSchema = Joi.object({
enabled: Joi.boolean().required(),
url: Joi.string().when('enabled', {
is: true,
then: Joi.required().uri({ scheme: ['http', 'https'] }),
otherwise: Joi.optional(),
}),
events: Joi.array().items(
Joi.string().valid(
'APPLICATION_STARTUP',
'INSTANCE_CREATE',
'INSTANCE_DELETE',
'QRCODE_UPDATED',
'CONNECTION_UPDATE',
'STATUS_INSTANCE',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'CHATS_SET',
'CHATS_UPDATE',
'CHATS_UPSERT',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUPS_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CALL'
)
).min(1).when('enabled', {
is: true,
then: Joi.required(),
otherwise: Joi.optional(),
}),
headers: Joi.object().pattern(
Joi.string(),
Joi.string()
).optional(),
byEvents: Joi.boolean().optional().default(false),
base64: Joi.boolean().optional().default(false),
}).required();
```
## Chatbot Validation Schemas
### Base Chatbot Validation
```typescript
export const baseChatbotSchema = Joi.object({
enabled: Joi.boolean().required(),
description: Joi.string().required().min(1).max(500),
expire: Joi.number().optional().min(0).max(86400), // 24 hours in seconds
keywordFinish: Joi.string().optional().max(100),
delayMessage: Joi.number().optional().min(0).max(10000),
unknownMessage: Joi.string().optional().max(1000),
listeningFromMe: Joi.boolean().optional().default(false),
stopBotFromMe: Joi.boolean().optional().default(false),
keepOpen: Joi.boolean().optional().default(false),
debounceTime: Joi.number().optional().min(0).max(60000),
triggerType: Joi.string().required().valid('ALL', 'KEYWORD', 'REGEX'),
triggerOperator: Joi.string().when('triggerType', {
is: 'KEYWORD',
then: Joi.required().valid('EQUALS', 'CONTAINS', 'STARTS_WITH', 'ENDS_WITH'),
otherwise: Joi.optional(),
}),
triggerValue: Joi.string().when('triggerType', {
is: Joi.valid('KEYWORD', 'REGEX'),
then: Joi.required().min(1).max(500),
otherwise: Joi.optional(),
}),
ignoreJids: Joi.array().items(Joi.string()).optional(),
splitMessages: Joi.boolean().optional().default(false),
timePerChar: Joi.number().optional().min(10).max(1000).default(100),
}).required();
export const typebotSchema = baseChatbotSchema.keys({
url: Joi.string().required().uri({ scheme: ['http', 'https'] }),
typebot: Joi.string().required().min(1).max(100),
apiVersion: Joi.string().optional().valid('v1', 'v2').default('v1'),
}).required();
export const openaiSchema = baseChatbotSchema.keys({
apiKey: Joi.string().required().min(10),
model: Joi.string().optional().valid(
'gpt-3.5-turbo',
'gpt-3.5-turbo-16k',
'gpt-4',
'gpt-4-32k',
'gpt-4-turbo-preview'
).default('gpt-3.5-turbo'),
systemMessage: Joi.string().optional().max(2000),
maxTokens: Joi.number().optional().min(1).max(4000).default(1000),
temperature: Joi.number().optional().min(0).max(2).default(0.7),
}).required();
```
## Business API Validation Schemas
### Template Validation
```typescript
export const templateSchema = Joi.object({
name: Joi.string().required().min(1).max(512).pattern(/^[a-z0-9_]+$/),
category: Joi.string().required().valid('MARKETING', 'UTILITY', 'AUTHENTICATION'),
allowCategoryChange: Joi.boolean().required(),
language: Joi.string().required().pattern(/^[a-z]{2}_[A-Z]{2}$/), // e.g., pt_BR, en_US
components: Joi.array().items(
Joi.object({
type: Joi.string().required().valid('HEADER', 'BODY', 'FOOTER', 'BUTTONS'),
format: Joi.string().when('type', {
is: 'HEADER',
then: Joi.valid('TEXT', 'IMAGE', 'VIDEO', 'DOCUMENT'),
otherwise: Joi.optional(),
}),
text: Joi.string().when('type', {
is: Joi.valid('HEADER', 'BODY', 'FOOTER'),
then: Joi.required().min(1).max(1024),
otherwise: Joi.optional(),
}),
buttons: Joi.array().when('type', {
is: 'BUTTONS',
then: Joi.items(
Joi.object({
type: Joi.string().required().valid('QUICK_REPLY', 'URL', 'PHONE_NUMBER'),
text: Joi.string().required().min(1).max(25),
url: Joi.string().when('type', {
is: 'URL',
then: Joi.required().uri(),
otherwise: Joi.optional(),
}),
phone_number: Joi.string().when('type', {
is: 'PHONE_NUMBER',
then: Joi.required().pattern(/^\+?\d+$/),
otherwise: Joi.optional(),
}),
})
).min(1).max(10),
otherwise: Joi.optional(),
}),
})
).min(1).required(),
webhookUrl: Joi.string().optional().uri({ scheme: ['http', 'https'] }),
}).required();
export const catalogSchema = Joi.object({
number: Joi.string().optional().pattern(/^\d+$/),
limit: Joi.number().optional().min(1).max(1000).default(10),
cursor: Joi.string().optional(),
}).optional();
```
## Group Validation Schemas
### Group Management Validation
```typescript
export const createGroupSchema = Joi.object({
subject: Joi.string().required().min(1).max(100),
description: Joi.string().optional().max(500),
participants: Joi.array().items(
Joi.string().pattern(/^\d+$/)
).min(1).max(256).required(),
promoteParticipants: Joi.boolean().optional().default(false),
}).required();
export const updateGroupSchema = Joi.object({
subject: Joi.string().optional().min(1).max(100),
description: Joi.string().optional().max(500),
}).min(1).required();
export const groupParticipantsSchema = Joi.object({
participants: Joi.array().items(
Joi.string().pattern(/^\d+$/)
).min(1).max(50).required(),
action: Joi.string().required().valid('add', 'remove', 'promote', 'demote'),
}).required();
```
## Label Validation Schemas
### Label Management Validation
```typescript
export const labelSchema = Joi.object({
name: Joi.string().required().min(1).max(100),
color: Joi.string().required().pattern(/^#[0-9A-Fa-f]{6}$/), // Hex color
predefinedId: Joi.string().optional(),
}).required();
export const handleLabelSchema = Joi.object({
number: Joi.string().required().pattern(/^\d+$/),
labelId: Joi.string().required(),
action: Joi.string().required().valid('add', 'remove'),
}).required();
```
## Custom Validation Functions
### Phone Number Validation
```typescript
export function validatePhoneNumber(number: string): boolean {
// Remove any non-digit characters
const cleaned = number.replace(/\D/g, '');
// Check minimum and maximum length
if (cleaned.length < 10 || cleaned.length > 15) {
return false;
}
// Check for valid country codes (basic validation)
const validCountryCodes = ['1', '7', '20', '27', '30', '31', '32', '33', '34', '36', '39', '40', '41', '43', '44', '45', '46', '47', '48', '49', '51', '52', '53', '54', '55', '56', '57', '58', '60', '61', '62', '63', '64', '65', '66', '81', '82', '84', '86', '90', '91', '92', '93', '94', '95', '98'];
// Check if starts with valid country code
const startsWithValidCode = validCountryCodes.some(code => cleaned.startsWith(code));
return startsWithValidCode;
}
export const phoneNumberValidator = Joi.string().custom((value, helpers) => {
if (!validatePhoneNumber(value)) {
return helpers.error('any.invalid');
}
return value;
}, 'Phone number validation');
```
### Base64 Validation
```typescript
export function validateBase64(base64: string): boolean {
try {
// Check if it's a valid base64 string
const decoded = Buffer.from(base64, 'base64').toString('base64');
return decoded === base64;
} catch {
return false;
}
}
export const base64Validator = Joi.string().custom((value, helpers) => {
if (!validateBase64(value)) {
return helpers.error('any.invalid');
}
return value;
}, 'Base64 validation');
```
### URL Validation with Protocol Check
```typescript
export function validateWebhookUrl(url: string): boolean {
try {
const parsed = new URL(url);
return ['http:', 'https:'].includes(parsed.protocol);
} catch {
return false;
}
}
export const webhookUrlValidator = Joi.string().custom((value, helpers) => {
if (!validateWebhookUrl(value)) {
return helpers.error('any.invalid');
}
return value;
}, 'Webhook URL validation');
```
## Validation Error Handling
### Error Message Customization
```typescript
export const validationMessages = {
'any.required': 'O campo {#label} é obrigatório',
'string.empty': 'O campo {#label} não pode estar vazio',
'string.min': 'O campo {#label} deve ter pelo menos {#limit} caracteres',
'string.max': 'O campo {#label} deve ter no máximo {#limit} caracteres',
'string.pattern.base': 'O campo {#label} possui formato inválido',
'number.min': 'O campo {#label} deve ser maior ou igual a {#limit}',
'number.max': 'O campo {#label} deve ser menor ou igual a {#limit}',
'array.min': 'O campo {#label} deve ter pelo menos {#limit} itens',
'array.max': 'O campo {#label} deve ter no máximo {#limit} itens',
'any.only': 'O campo {#label} deve ser um dos valores: {#valids}',
};
export function formatValidationError(error: Joi.ValidationError): any {
return {
message: 'Dados de entrada inválidos',
details: error.details.map(detail => ({
field: detail.path.join('.'),
message: detail.message,
value: detail.context?.value,
})),
};
}
```
## Schema Composition
### Reusable Schema Components
```typescript
export const commonFields = {
instanceName: Joi.string().required().min(1).max(100).pattern(/^[a-zA-Z0-9_-]+$/),
number: phoneNumberValidator.required(),
delay: Joi.number().optional().min(0).max(60000),
enabled: Joi.boolean().optional().default(true),
};
export const mediaFields = {
mediatype: Joi.string().required().valid('image', 'video', 'audio', 'document'),
media: Joi.alternatives().try(
Joi.string().uri(),
base64Validator,
).required(),
caption: Joi.string().optional().max(1024),
fileName: Joi.string().optional().max(255),
};
// Compose schemas using common fields
export const quickMessageSchema = Joi.object({
...commonFields,
text: Joi.string().required().min(1).max(4096),
}).required();
export const quickMediaSchema = Joi.object({
...commonFields,
...mediaFields,
}).required();
```
================================================
FILE: .dockerignore
================================================
.git
*Dockerfile*
*docker-compose*
.env
node_modules
dist
================================================
FILE: .eslintignore
================================================
/node-modules
/dist
================================================
FILE: .eslintrc.js
================================================
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
warnOnUnsupportedTypeScriptVersion: false,
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
},
plugins: ['@typescript-eslint', 'simple-import-sort', 'import'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unused-vars': 'error',
'import/first': 'error',
'import/no-duplicates': 'error',
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-wrapper-object-types': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
'prettier/prettier': ['error', { endOfLine: 'auto' }],
},
};
================================================
FILE: .github/ISSUE_TEMPLATE/-en--bug-report.yaml
================================================
name: Bug Report
description: Create a report to help us improve.
labels:
- bug
- en
# - help wanted
# Automatically assign the issue to:
# assignees: DavidsonGomes
body:
- type: checkboxes
id: terms
attributes:
label: Welcome!
description: |
The issue tracker is only for reporting bugs and feature requests.
For user-related support questions, please visit:
- [Discord](https://evolution-api.com/discord)
- [WhatsApp Group](https://evolution-api.com/whatsapp)
<br/>
**DO NOT OPEN AN ISSUE FOR GENERAL SUPPORT QUESTIONS.**
options:
- label: Yes, I have searched for similar issues on [GitHub](https://github.com/EvolutionAPI/evolution-api/issues) and found none.
required: true
- type: textarea
attributes:
label: What did you do?
description: |
How to write a good bug report?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions that led you to report this issue: the context.
- The context should lead to something, an idea or problem you are facing.
- Be clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
placeholder: Describe the problem you encountered in detail.
validations:
required: true
- type: textarea
attributes:
label: What did you expect?
placeholder: Describe what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: What did you observe instead of what you expected?
placeholder: Explain what actually happens when you follow the steps above.
validations:
required: true
- type: textarea
attributes:
label: Screenshots/Videos
placeholder: |
If possible, add screenshots or videos that illustrate the problem. This can be extremely helpful in understanding the issue better.
- type: textarea
attributes:
label: Which version of the API are you using?
description: |
Enter the version number found in the `version` property of the **package.json**.
placeholder: Paste the version here.
validations:
required: true
- type: dropdown
id: select
attributes:
label: What is your environment?
options:
- Windows
- Linux
- Mac
- Docker
- Other
validations:
required: true
- type: textarea
attributes:
label: Other environment specifications
placeholder: 'Hardware/Software: [e.g., CPU, GPU]'
validations:
required: false
- type: textarea
attributes:
label: If applicable, paste the log output
description: |
Please attach any logs that might be related to the issue.
If the logs contain sensitive information, consider sending them privately to one of the project maintainers.
placeholder: Paste the application log here.
validations:
required: false
- type: textarea
attributes:
label: Additional Notes
description: Include any other information you think might be useful to understand or resolve the bug.
validations:
required: false
================================================
FILE: .github/ISSUE_TEMPLATE/-en--feature-request.yaml
================================================
name: Feature Request
description: Suggest ideas for the project.
labels:
- enhancement
- en
# Automatically assign the issue to:
# assignees: DavidsonGomes
body:
- type: checkboxes
id: terms
attributes:
label: Welcome!
description: '**DO NOT OPEN FOR GENERAL SUPPORT QUESTIONS.**'
options:
- label: Yes, I have searched for similar requests on [GitHub](https://github.com/code-chat-br/whatsapp-api/issues) and found none.
required: true
- type: dropdown
attributes:
label: What type of feature?
description: |
How to write a good feature request?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions that led you to suggest this feature: the context.
- The context should lead to something, an idea or problem you are facing.
- Be clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
options:
- Integration
- Functionality
- Endpoint
- Database adjustment
- Other
validations:
required: true
- type: textarea
attributes:
label: What is the motivation for the request?
description: |
What problem does the feature seek to solve?
Clearly and in detail describe the functionality you want to be implemented.
Explain how it fits into the context of the project.
placeholder: Detailed description
validations:
required: true
- type: textarea
attributes:
label: Usage Examples
description: |
Provide specific examples of how this functionality could be used.
This can include scenarios or use cases where the feature would be particularly beneficial.
placeholder: text - image - video - flowcharts
validations:
required: false
- type: textarea
attributes:
label: How should the feature be developed?
description: |
Should it be inserted directly into the code?
Should it be built as a different application that acts as an extension of the API?
For example: a `worker`?
Discuss how this new functionality could impact other parts of the project, if applicable.
---
If you have ideas on how this functionality could be implemented, please share them here.
This is not mandatory, but it can be helpful for the development team.
placeholder: Insert feature ideas here
validations:
required: false
- type: textarea
attributes:
label: Additional Notes
description: Any other information you believe is relevant to your request.
placeholder: Insert your observations here.
validations:
required: false
================================================
FILE: .github/ISSUE_TEMPLATE/-pt--reportar-bug.yaml
================================================
name: Relatório de bug
description: Crie um relatório para nos ajudar a melhorar.
labels:
- bug
- pt-br
# - help wanted
# Atrubuir automaticamente a issue a:
# assignees: DavidsonGomes
body:
- type: checkboxes
id: termos
attributes:
label: Bem-vido!
description: |
O rastreador de problemas é apenas para relatar bugs e solicitações de recursos.
Para perguntas de suporte relacionadas ao usuário final, acesse:
- [Discord](https://evolution-api.com/discord)
- [Grupo do WhatsApp](https://evolution-api.com/whatsapp)
<br/>
**NÃO ABRA UM PROBLEMA PARA PERGUNTAS GERAIS DE SUPORTE.**
options:
- label: Sim, pesquisei problemas semelhantes no [GitHub](https://github.com/EvolutionAPI/evolution-api/issues) e não encontrei nenhum.
required: true
- type: textarea
attributes:
label: O que você fez?
description: |
Como escrever um bom relatório de bug?
- Respeite o modelo de problema tanto quanto possível.
- O título deve ser curto e descritivo.
- Explique as condições que o levaram a reportar este problema: o contexto.
- O contexto deve levar a algo, ideia ou problema que você está enfrentando.
- Seja claro e conciso.
- Formate suas mensagens para ajudar o leitor a se concentrar no que importa e entender a estrutura da sua mensagem, use [sintaxe Markdown](https://help.github.com/articles/github-flavored-markdown)
placeholder: Descreva detalhadamente o problema que você encontrou.
validations:
required: true
- type: textarea
attributes:
label: O que você esperava?
placeholder: Descreva o que você esperava que acontecesse.
validations:
required: true
- type: textarea
attributes:
label: O que vc observou ao invés do que esperava?
placeholder: Explique o que realmente acontece quando você segue os passos acima.
validations:
required: true
- type: textarea
attributes:
label: Capturas de Tela/Vídeos
placeholder: |
Se possível, adicione capturas de tela ou vídeos que ilustrem o problema. Isso pode ser extremamente útil para entender melhor o problema.
- type: textarea
attributes:
label: Qual versão da API você está usando?
description: |
Insira o número da sua versão que está na propriedade `version` do **package.json**.
placeholder: Cole aqui a versão.
validations:
required: true
- type: dropdown
id: select
attributes:
label: Qual é o seu ambiente?
options:
- Windows
- Linux
- Mac
- Docker
- Outro
validations:
required: true
gitextract_y8izy66h/ ├── .cursor/ │ └── rules/ │ ├── README.md │ ├── core-development.mdc │ ├── cursor.json │ ├── project-context.mdc │ └── specialized-rules/ │ ├── controller-rules.mdc │ ├── dto-rules.mdc │ ├── guard-rules.mdc │ ├── integration-channel-rules.mdc │ ├── integration-chatbot-rules.mdc │ ├── integration-event-rules.mdc │ ├── integration-storage-rules.mdc │ ├── route-rules.mdc │ ├── service-rules.mdc │ ├── type-rules.mdc │ ├── util-rules.mdc │ └── validate-rules.mdc ├── .dockerignore ├── .eslintignore ├── .eslintrc.js ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── -en--bug-report.yaml │ │ ├── -en--feature-request.yaml │ │ ├── -pt--reportar-bug.yaml │ │ ├── -pt--solicitar-recurso.yaml │ │ ├── bug_report.yml │ │ └── feature_request.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── check_code_quality.yml │ ├── publish_docker_image.yml │ ├── publish_docker_image_homolog.yml │ ├── publish_docker_image_latest.yml │ └── security.yml ├── .gitignore ├── .gitmodules ├── .husky/ │ ├── README.md │ ├── commit-msg │ ├── pre-commit │ └── pre-push ├── .prettierrc.js ├── .vscode/ │ └── settings.json ├── AGENTS.md ├── CHANGELOG.md ├── CLAUDE.md ├── Docker/ │ ├── kafka/ │ │ └── docker-compose.yaml │ ├── minio/ │ │ └── docker-compose.yaml │ ├── mysql/ │ │ └── docker-compose.yaml │ ├── postgres/ │ │ └── docker-compose.yaml │ ├── rabbitmq/ │ │ └── docker-compose.yaml │ ├── redis/ │ │ └── docker-compose.yaml │ ├── scripts/ │ │ ├── deploy_database.sh │ │ ├── env_functions.sh │ │ └── generate_database.sh │ └── swarm/ │ └── evolution_api_v2.yaml ├── Dockerfile ├── Dockerfile.metrics ├── Extras/ │ └── chatwoot/ │ ├── configurar_admin.json │ ├── criador_de_empresas.json │ └── criador_de_inbox.json ├── LICENSE ├── README.md ├── SECURITY.md ├── commitlint.config.js ├── docker-compose.dev.yaml ├── docker-compose.yaml ├── env.example ├── grafana-dashboard.json.example ├── local_install.sh ├── manager/ │ └── dist/ │ ├── assets/ │ │ ├── index-CO3NSIFj.js │ │ └── index-DsIrum0U.css │ └── index.html ├── manager_install.sh ├── package.json ├── prisma/ │ ├── mysql-migrations/ │ │ ├── 20240809105427_init/ │ │ │ └── migration.sql │ │ ├── 20240813153900_add_unique_index_for_remoted_jid_and_instance_in_contacts/ │ │ │ └── migration.sql │ │ ├── 20240814173138_add_ignore_jids_chatwoot/ │ │ │ └── migration.sql │ │ ├── 20240814214314_integrations_unification/ │ │ │ └── migration.sql │ │ ├── 20240821203259_add_postgres_migrations/ │ │ │ └── migration.sql │ │ ├── 20240824162012_add_type_on_integration_sessions/ │ │ │ └── migration.sql │ │ ├── 20240825131301_change_to_evolution_bot/ │ │ │ └── migration.sql │ │ ├── 20241001172800_add_message_status/ │ │ │ └── migration.sql │ │ ├── 20241108101333_fix_message_status_as_string/ │ │ │ └── migration.sql │ │ ├── 20250214181954_add_wavoip_token_column/ │ │ │ └── migration.sql │ │ ├── 20250225180031_add_nats_integration/ │ │ │ └── migration.sql │ │ ├── 20250510035200_add_wavoip_token_to_settings_table/ │ │ │ └── migration.sql │ │ ├── 20250514232744_add_n8n_table/ │ │ │ └── migration.sql │ │ ├── 20250515211815_add_evoai_table/ │ │ │ └── migration.sql │ │ ├── 20250516012152_remove_unique_atribute_for_file_name_in_media/ │ │ │ └── migration.sql │ │ ├── 20250612155048_add_coluns_trypebot_tables/ │ │ │ └── migration.sql │ │ ├── 20250613143000_add_lid_column_to_is_onwhatsapp/ │ │ │ └── migration.sql │ │ ├── 20250918183910_add_kafka_integration/ │ │ │ └── migration.sql │ │ └── migration_lock.toml │ ├── mysql-schema.prisma │ ├── postgresql-migrations/ │ │ ├── 20240609181238_init/ │ │ │ └── migration.sql │ │ ├── 20240610144159_create_column_profile_name_instance/ │ │ │ └── migration.sql │ │ ├── 20240611125754_create_columns_whitelabel_chatwoot/ │ │ │ └── migration.sql │ │ ├── 20240611202817_create_columns_debounce_time_typebot/ │ │ │ └── migration.sql │ │ ├── 20240712144948_add_business_id_column_to_instances/ │ │ │ └── migration.sql │ │ ├── 20240712150256_create_templates_table/ │ │ │ └── migration.sql │ │ ├── 20240712155950_adjusts_in_templates_table/ │ │ │ └── migration.sql │ │ ├── 20240712162206_remove_templates_table/ │ │ │ └── migration.sql │ │ ├── 20240712223655_column_fallback_typebot/ │ │ │ └── migration.sql │ │ ├── 20240712230631_column_ignore_jids_typebot/ │ │ │ └── migration.sql │ │ ├── 20240713184337_add_media_table/ │ │ │ └── migration.sql │ │ ├── 20240718121437_add_openai_tables/ │ │ │ └── migration.sql │ │ ├── 20240718123923_adjusts_openai_tables/ │ │ │ └── migration.sql │ │ ├── 20240722173259_add_name_column_to_openai_creds/ │ │ │ └── migration.sql │ │ ├── 20240722173518_add_name_column_to_openai_creds/ │ │ │ └── migration.sql │ │ ├── 20240723152648_adjusts_in_column_openai_creds/ │ │ │ └── migration.sql │ │ ├── 20240723200254_add_webhookurl_on_message/ │ │ │ └── migration.sql │ │ ├── 20240725184147_create_template_table/ │ │ │ └── migration.sql │ │ ├── 20240725202651_add_webhook_url_template_table/ │ │ │ └── migration.sql │ │ ├── 20240725221646_modify_token_instance_table/ │ │ │ └── migration.sql │ │ ├── 20240729115127_modify_trigger_type_openai_typebot_table/ │ │ │ └── migration.sql │ │ ├── 20240729180347_modify_typebot_session_status_openai_typebot_table/ │ │ │ └── migration.sql │ │ ├── 20240730152156_create_dify_tables/ │ │ │ └── migration.sql │ │ ├── 20240801193907_add_column_speech_to_text_openai_setting_table/ │ │ │ └── migration.sql │ │ ├── 20240803163908_add_column_description_on_integrations_table/ │ │ │ └── migration.sql │ │ ├── 20240808210239_add_column_function_url_openaibot_table/ │ │ │ └── migration.sql │ │ ├── 20240811021156_add_chat_name_column/ │ │ │ └── migration.sql │ │ ├── 20240811183328_add_unique_index_for_remoted_jid_and_instance_in_contacts/ │ │ │ └── migration.sql │ │ ├── 20240813003116_make_label_unique_for_instance/ │ │ │ └── migration.sql │ │ ├── 20240814173033_add_ignore_jids_chatwoot/ │ │ │ └── migration.sql │ │ ├── 20240814202359_integrations_unification/ │ │ │ └── migration.sql │ │ ├── 20240817110155_add_trigger_type_advanced/ │ │ │ └── migration.sql │ │ ├── 20240819154941_add_context_to_integration_session/ │ │ │ └── migration.sql │ │ ├── 20240821120816_bot_id_integration_session/ │ │ │ └── migration.sql │ │ ├── 20240821171327_add_generic_bot_table/ │ │ │ └── migration.sql │ │ ├── 20240821194524_add_flowise_table/ │ │ │ └── migration.sql │ │ ├── 20240824161333_add_type_on_integration_sessions/ │ │ │ └── migration.sql │ │ ├── 20240825130616_change_to_evolution_bot/ │ │ │ └── migration.sql │ │ ├── 20240828140837_add_is_on_whatsapp_table/ │ │ │ └── migration.sql │ │ ├── 20240828141556_remove_name_column_from_on_whatsapp_table/ │ │ │ └── migration.sql │ │ ├── 20240830193533_changed_table_case/ │ │ │ └── migration.sql │ │ ├── 20240906202019_add_headers_on_webhook_config/ │ │ │ └── migration.sql │ │ ├── 20241001180457_add_message_status/ │ │ │ └── migration.sql │ │ ├── 20241006130306_alter_status_on_message_table/ │ │ │ └── migration.sql │ │ ├── 20241007164026_add_unread_messages_on_chat_table/ │ │ │ └── migration.sql │ │ ├── 20241011085129_create_pusher_table/ │ │ │ └── migration.sql │ │ ├── 20241011100803_split_messages_and_time_per_char_integrations/ │ │ │ └── migration.sql │ │ ├── 20241017144950_create_index/ │ │ │ └── migration.sql │ │ ├── 20250116001415_add_wavoip_token_to_settings_table/ │ │ │ └── migration.sql │ │ ├── 20250225180031_add_nats_integration/ │ │ │ └── migration.sql │ │ ├── 20250514232744_add_n8n_table/ │ │ │ └── migration.sql │ │ ├── 20250515211815_add_evoai_table/ │ │ │ └── migration.sql │ │ ├── 20250516012152_remove_unique_atribute_for_file_name_in_media/ │ │ │ └── migration.sql │ │ ├── 20250612155048_add_coluns_trypebot_tables/ │ │ │ └── migration.sql │ │ ├── 20250613143000_add_lid_column_to_is_onwhatsapp/ │ │ │ └── migration.sql │ │ ├── 20250918182355_add_kafka_integration/ │ │ │ └── migration.sql │ │ ├── 20251122003044_add_chat_instance_remotejid_unique/ │ │ │ └── migration.sql │ │ └── migration_lock.toml │ ├── postgresql-schema.prisma │ └── psql_bouncer-schema.prisma ├── prometheus.yml.example ├── runWithProvider.js ├── src/ │ ├── @types/ │ │ └── express.d.ts │ ├── api/ │ │ ├── abstract/ │ │ │ ├── abstract.cache.ts │ │ │ ├── abstract.repository.ts │ │ │ └── abstract.router.ts │ │ ├── controllers/ │ │ │ ├── business.controller.ts │ │ │ ├── call.controller.ts │ │ │ ├── chat.controller.ts │ │ │ ├── group.controller.ts │ │ │ ├── instance.controller.ts │ │ │ ├── label.controller.ts │ │ │ ├── proxy.controller.ts │ │ │ ├── sendMessage.controller.ts │ │ │ ├── settings.controller.ts │ │ │ └── template.controller.ts │ │ ├── dto/ │ │ │ ├── business.dto.ts │ │ │ ├── call.dto.ts │ │ │ ├── chat.dto.ts │ │ │ ├── chatbot.dto.ts │ │ │ ├── group.dto.ts │ │ │ ├── instance.dto.ts │ │ │ ├── label.dto.ts │ │ │ ├── proxy.dto.ts │ │ │ ├── sendMessage.dto.ts │ │ │ ├── settings.dto.ts │ │ │ └── template.dto.ts │ │ ├── guards/ │ │ │ ├── auth.guard.ts │ │ │ ├── instance.guard.ts │ │ │ └── telemetry.guard.ts │ │ ├── integrations/ │ │ │ ├── channel/ │ │ │ │ ├── channel.controller.ts │ │ │ │ ├── channel.router.ts │ │ │ │ ├── evolution/ │ │ │ │ │ ├── evolution.channel.service.ts │ │ │ │ │ ├── evolution.controller.ts │ │ │ │ │ └── evolution.router.ts │ │ │ │ ├── meta/ │ │ │ │ │ ├── meta.controller.ts │ │ │ │ │ ├── meta.router.ts │ │ │ │ │ └── whatsapp.business.service.ts │ │ │ │ └── whatsapp/ │ │ │ │ ├── baileys.controller.ts │ │ │ │ ├── baileys.router.ts │ │ │ │ ├── baileysMessage.processor.ts │ │ │ │ ├── voiceCalls/ │ │ │ │ │ ├── transport.type.ts │ │ │ │ │ └── useVoiceCallsBaileys.ts │ │ │ │ └── whatsapp.baileys.service.ts │ │ │ ├── chatbot/ │ │ │ │ ├── base-chatbot.controller.ts │ │ │ │ ├── base-chatbot.dto.ts │ │ │ │ ├── base-chatbot.service.ts │ │ │ │ ├── chatbot.controller.ts │ │ │ │ ├── chatbot.router.ts │ │ │ │ ├── chatbot.schema.ts │ │ │ │ ├── chatwoot/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── chatwoot.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── chatwoot.dto.ts │ │ │ │ │ ├── libs/ │ │ │ │ │ │ └── postgres.client.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── chatwoot.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── chatwoot.service.ts │ │ │ │ │ ├── utils/ │ │ │ │ │ │ └── chatwoot-import-helper.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── chatwoot.schema.ts │ │ │ │ ├── dify/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── dify.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── dify.dto.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── dify.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── dify.service.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── dify.schema.ts │ │ │ │ ├── evoai/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── evoai.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── evoai.dto.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── evoai.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── evoai.service.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── evoai.schema.ts │ │ │ │ ├── evolutionBot/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── evolutionBot.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── evolutionBot.dto.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── evolutionBot.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── evolutionBot.service.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── evolutionBot.schema.ts │ │ │ │ ├── flowise/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── flowise.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── flowise.dto.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── flowise.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── flowise.service.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── flowise.schema.ts │ │ │ │ ├── n8n/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── n8n.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── n8n.dto.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── n8n.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── n8n.service.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── n8n.schema.ts │ │ │ │ ├── openai/ │ │ │ │ │ ├── controllers/ │ │ │ │ │ │ └── openai.controller.ts │ │ │ │ │ ├── dto/ │ │ │ │ │ │ └── openai.dto.ts │ │ │ │ │ ├── routes/ │ │ │ │ │ │ └── openai.router.ts │ │ │ │ │ ├── services/ │ │ │ │ │ │ └── openai.service.ts │ │ │ │ │ └── validate/ │ │ │ │ │ └── openai.schema.ts │ │ │ │ └── typebot/ │ │ │ │ ├── controllers/ │ │ │ │ │ └── typebot.controller.ts │ │ │ │ ├── dto/ │ │ │ │ │ └── typebot.dto.ts │ │ │ │ ├── routes/ │ │ │ │ │ └── typebot.router.ts │ │ │ │ ├── services/ │ │ │ │ │ └── typebot.service.ts │ │ │ │ └── validate/ │ │ │ │ └── typebot.schema.ts │ │ │ ├── event/ │ │ │ │ ├── event.controller.ts │ │ │ │ ├── event.dto.ts │ │ │ │ ├── event.manager.ts │ │ │ │ ├── event.router.ts │ │ │ │ ├── event.schema.ts │ │ │ │ ├── kafka/ │ │ │ │ │ ├── kafka.controller.ts │ │ │ │ │ ├── kafka.router.ts │ │ │ │ │ └── kafka.schema.ts │ │ │ │ ├── nats/ │ │ │ │ │ ├── nats.controller.ts │ │ │ │ │ └── nats.router.ts │ │ │ │ ├── pusher/ │ │ │ │ │ ├── pusher.controller.ts │ │ │ │ │ ├── pusher.router.ts │ │ │ │ │ └── pusher.schema.ts │ │ │ │ ├── rabbitmq/ │ │ │ │ │ ├── rabbitmq.controller.ts │ │ │ │ │ └── rabbitmq.router.ts │ │ │ │ ├── sqs/ │ │ │ │ │ ├── sqs.controller.ts │ │ │ │ │ └── sqs.router.ts │ │ │ │ ├── webhook/ │ │ │ │ │ ├── webhook.controller.ts │ │ │ │ │ ├── webhook.router.ts │ │ │ │ │ └── webhook.schema.ts │ │ │ │ └── websocket/ │ │ │ │ ├── websocket.controller.ts │ │ │ │ └── websocket.router.ts │ │ │ ├── integration.dto.ts │ │ │ └── storage/ │ │ │ ├── s3/ │ │ │ │ ├── controllers/ │ │ │ │ │ └── s3.controller.ts │ │ │ │ ├── dto/ │ │ │ │ │ └── media.dto.ts │ │ │ │ ├── libs/ │ │ │ │ │ └── minio.server.ts │ │ │ │ ├── routes/ │ │ │ │ │ └── s3.router.ts │ │ │ │ ├── services/ │ │ │ │ │ └── s3.service.ts │ │ │ │ └── validate/ │ │ │ │ └── s3.schema.ts │ │ │ └── storage.router.ts │ │ ├── provider/ │ │ │ └── sessions.ts │ │ ├── repository/ │ │ │ └── repository.service.ts │ │ ├── routes/ │ │ │ ├── business.router.ts │ │ │ ├── call.router.ts │ │ │ ├── chat.router.ts │ │ │ ├── group.router.ts │ │ │ ├── index.router.ts │ │ │ ├── instance.router.ts │ │ │ ├── label.router.ts │ │ │ ├── proxy.router.ts │ │ │ ├── sendMessage.router.ts │ │ │ ├── settings.router.ts │ │ │ ├── template.router.ts │ │ │ └── view.router.ts │ │ ├── server.module.ts │ │ ├── services/ │ │ │ ├── auth.service.ts │ │ │ ├── cache.service.ts │ │ │ ├── channel.service.ts │ │ │ ├── monitor.service.ts │ │ │ ├── proxy.service.ts │ │ │ ├── settings.service.ts │ │ │ └── template.service.ts │ │ └── types/ │ │ └── wa.types.ts │ ├── cache/ │ │ ├── cacheengine.ts │ │ ├── localcache.ts │ │ ├── rediscache.client.ts │ │ └── rediscache.ts │ ├── config/ │ │ ├── env.config.ts │ │ ├── error.config.ts │ │ ├── event.config.ts │ │ ├── logger.config.ts │ │ └── path.config.ts │ ├── exceptions/ │ │ ├── 400.exception.ts │ │ ├── 401.exception.ts │ │ ├── 403.exception.ts │ │ ├── 404.exception.ts │ │ ├── 500.exception.ts │ │ └── index.ts │ ├── main.ts │ ├── railway.json │ ├── utils/ │ │ ├── advancedOperatorsSearch.ts │ │ ├── createJid.ts │ │ ├── errorResponse.ts │ │ ├── fetchLatestWaWebVersion.ts │ │ ├── findBotByTrigger.ts │ │ ├── getConversationMessage.ts │ │ ├── i18n.ts │ │ ├── instrumentSentry.ts │ │ ├── makeProxyAgent.ts │ │ ├── onWhatsappCache.ts │ │ ├── renderStatus.ts │ │ ├── sendTelemetry.ts │ │ ├── server-up.ts │ │ ├── translations/ │ │ │ ├── en.json │ │ │ ├── es.json │ │ │ └── pt-BR.json │ │ ├── use-multi-file-auth-state-prisma.ts │ │ ├── use-multi-file-auth-state-provider-files.ts │ │ └── use-multi-file-auth-state-redis-db.ts │ └── validate/ │ ├── business.schema.ts │ ├── chat.schema.ts │ ├── group.schema.ts │ ├── instance.schema.ts │ ├── label.schema.ts │ ├── message.schema.ts │ ├── proxy.schema.ts │ ├── settings.schema.ts │ ├── template.schema.ts │ ├── templateDelete.schema.ts │ ├── templateEdit.schema.ts │ └── validate.schema.ts ├── tsconfig.json └── tsup.config.ts
Showing preview only (303K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3234 symbols across 188 files)
FILE: manager/dist/assets/index-CO3NSIFj.js
function Bk (line 1) | function Bk(e,t){for(var n=0;n<t.length;n++){const r=t[n];if(typeof r!="...
function n (line 1) | function n(s){const o={};return s.integrity&&(o.integrity=s.integrity),s...
function r (line 1) | function r(s){if(s.ep)return;s.ep=!0;const o=n(s);fetch(s.href,o)}
function fd (line 1) | function fd(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.c...
function ND (line 9) | function ND(){if(A0)return Et;A0=1;var e=Symbol.for("react.element"),t=S...
function pd (line 9) | function pd(){return D0||(D0=1,iv.exports=ND()),iv.exports}
function MD (line 17) | function MD(){if(F0)return Xc;F0=1;var e=pd(),t=Symbol.for("react.elemen...
function _D (line 17) | function _D(){return L0||(L0=1,av.exports=MD()),av.exports}
method constructor (line 17) | constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(...
method subscribe (line 17) | subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.l...
method hasListeners (line 17) | hasListeners(){return this.listeners.size>0}
method onSubscribe (line 17) | onSubscribe(){}
method onUnsubscribe (line 17) | onUnsubscribe(){}
function ss (line 17) | function ss(){}
function RD (line 17) | function RD(e,t){return typeof e=="function"?e(t):e}
function Sy (line 17) | function Sy(e){return typeof e=="number"&&e>=0&&e!==1/0}
function zk (line 17) | function zk(e,t){return Math.max(e+(t||0)-Date.now(),0)}
function _l (line 17) | function _l(e,t){return typeof e=="function"?e(t):e}
function ws (line 17) | function ws(e,t){return typeof e=="function"?e(t):e}
function $0 (line 17) | function $0(e,t){const{type:n="all",exact:r,fetchStatus:s,predicate:o,qu...
function B0 (line 17) | function B0(e,t){const{exact:n,status:r,predicate:s,mutationKey:o}=e;if(...
function _b (line 17) | function _b(e,t){return(t?.queryKeyHashFn||xi)(e)}
function xi (line 17) | function xi(e){return JSON.stringify(e,(t,n)=>Cy(n)?Object.keys(n).sort(...
function Ou (line 17) | function Ou(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="...
function Uk (line 17) | function Uk(e,t){if(e===t)return e;const n=z0(e)&&z0(t);if(n||Cy(e)&&Cy(...
function Mp (line 17) | function Mp(e,t){if(!t||Object.keys(e).length!==Object.keys(t).length)re...
function z0 (line 17) | function z0(e){return Array.isArray(e)&&e.length===Object.keys(e).length}
function Cy (line 17) | function Cy(e){if(!U0(e))return!1;const t=e.constructor;if(t===void 0)re...
function U0 (line 17) | function U0(e){return Object.prototype.toString.call(e)==="[object Objec...
function PD (line 17) | function PD(e){return new Promise(t=>{setTimeout(t,e)})}
function Ey (line 17) | function Ey(e,t,n){return typeof n.structuralSharing=="function"?n.struc...
function OD (line 17) | function OD(e,t,n=0){const r=[...e,t];return n&&r.length>n?r.slice(1):r}
function ID (line 17) | function ID(e,t,n=0){const r=[t,...e];return n&&r.length>n?r.slice(0,-1):r}
function Hk (line 17) | function Hk(e,t){return!e.queryFn&&t?.initialPromise?()=>t.initialPromis...
method constructor (line 17) | constructor(){super(),this.#r=e=>{if(!Fl&&window.addEventListener){const...
method onSubscribe (line 17) | onSubscribe(){this.#t||this.setEventListener(this.#r)}
method onUnsubscribe (line 17) | onUnsubscribe(){this.hasListeners()||(this.#t?.(),this.#t=void 0)}
method setEventListener (line 17) | setEventListener(e){this.#r=e,this.#t?.(),this.#t=e(t=>{typeof t=="boole...
method setFocused (line 17) | setFocused(e){this.#e!==e&&(this.#e=e,this.onFocus())}
method onFocus (line 17) | onFocus(){const e=this.isFocused();this.listeners.forEach(t=>{t(e)})}
method isFocused (line 17) | isFocused(){return typeof this.#e=="boolean"?this.#e:globalThis.document...
method constructor (line 17) | constructor(){super(),this.#r=e=>{if(!Fl&&window.addEventListener){const...
method onSubscribe (line 17) | onSubscribe(){this.#t||this.setEventListener(this.#r)}
method onUnsubscribe (line 17) | onUnsubscribe(){this.hasListeners()||(this.#t?.(),this.#t=void 0)}
method setEventListener (line 17) | setEventListener(e){this.#r=e,this.#t?.(),this.#t=e(this.setOnline.bind(...
method setOnline (line 17) | setOnline(e){this.#e!==e&&(this.#e=e,this.listeners.forEach(n=>{n(e)}))}
method isOnline (line 17) | isOnline(){return this.#e}
function FD (line 17) | function FD(e){return Math.min(1e3*2**e,3e4)}
function qk (line 17) | function qk(e){return(e??"online")==="online"?_p.isOnline():!0}
method constructor (line 17) | constructor(e){super("CancelledError"),this.revert=e?.revert,this.silent...
function lv (line 17) | function lv(e){return e instanceof Kk}
function Wk (line 17) | function Wk(e){let t=!1,n=0,r=!1,s,o,l;const u=new Promise((k,j)=>{o=k,l...
function LD (line 17) | function LD(){let e=[],t=0,n=g=>{g()},r=g=>{g()},s=g=>setTimeout(g,0);co...
method destroy (line 17) | destroy(){this.clearGcTimeout()}
method scheduleGc (line 17) | scheduleGc(){this.clearGcTimeout(),Sy(this.gcTime)&&(this.#e=setTimeout(...
method updateGcTime (line 17) | updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(Fl?1/0:300*1e3))}
method clearGcTimeout (line 17) | clearGcTimeout(){this.#e&&(clearTimeout(this.#e),this.#e=void 0)}
method constructor (line 17) | constructor(e){super(),this.#o=!1,this.#a=e.defaultOptions,this.setOptio...
method meta (line 17) | get meta(){return this.options.meta}
method promise (line 17) | get promise(){return this.#n?.promise}
method setOptions (line 17) | setOptions(e){this.options={...this.#a,...e},this.updateGcTime(this.opti...
method optionalRemove (line 17) | optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"...
method setData (line 17) | setData(e,t){const n=Ey(this.state.data,e,this.options);return this.#s({...
method setState (line 17) | setState(e,t){this.#s({type:"setState",state:e,setStateOptions:t})}
method cancel (line 17) | cancel(e){const t=this.#n?.promise;return this.#n?.cancel(e),t?t.then(ss...
method destroy (line 17) | destroy(){super.destroy(),this.cancel({silent:!0})}
method reset (line 17) | reset(){this.destroy(),this.setState(this.#e)}
method isActive (line 17) | isActive(){return this.observers.some(e=>ws(e.options.enabled,this)!==!1)}
method isDisabled (line 17) | isDisabled(){return this.getObserversCount()>0&&!this.isActive()}
method isStale (line 17) | isStale(){return this.state.isInvalidated?!0:this.getObserversCount()>0?...
method isStaleByTime (line 17) | isStaleByTime(e=0){return this.state.isInvalidated||this.state.data===vo...
method onFocus (line 17) | onFocus(){this.observers.find(t=>t.shouldFetchOnWindowFocus())?.refetch(...
method onOnline (line 17) | onOnline(){this.observers.find(t=>t.shouldFetchOnReconnect())?.refetch({...
method addObserver (line 17) | addObserver(e){this.observers.includes(e)||(this.observers.push(e),this....
method removeObserver (line 17) | removeObserver(e){this.observers.includes(e)&&(this.observers=this.obser...
method getObserversCount (line 17) | getObserversCount(){return this.observers.length}
method invalidate (line 17) | invalidate(){this.state.isInvalidated||this.#s({type:"invalidate"})}
method fetch (line 17) | fetch(e,t){if(this.state.fetchStatus!=="idle"){if(this.state.data!==void...
method #s (line 17) | #s(e){const t=n=>{switch(e.type){case"failed":return{...n,fetchFailureCo...
function Jk (line 17) | function Jk(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetc...
function BD (line 17) | function BD(e){const t=typeof e.initialData=="function"?e.initialData():...
method constructor (line 17) | constructor(e={}){super(),this.config=e,this.#e=new Map}
method build (line 17) | build(e,t,n){const r=t.queryKey,s=t.queryHash??_b(r,t);let o=this.get(s)...
method add (line 17) | add(e){this.#e.has(e.queryHash)||(this.#e.set(e.queryHash,e),this.notify...
method remove (line 17) | remove(e){const t=this.#e.get(e.queryHash);t&&(e.destroy(),t===e&&this.#...
method clear (line 17) | clear(){Fn.batch(()=>{this.getAll().forEach(e=>{this.remove(e)})})}
method get (line 17) | get(e){return this.#e.get(e)}
method getAll (line 17) | getAll(){return[...this.#e.values()]}
method find (line 17) | find(e){const t={exact:!0,...e};return this.getAll().find(n=>$0(t,n))}
method findAll (line 17) | findAll(e={}){const t=this.getAll();return Object.keys(e).length>0?t.fil...
method notify (line 17) | notify(e){Fn.batch(()=>{this.listeners.forEach(t=>{t(e)})})}
method onFocus (line 17) | onFocus(){Fn.batch(()=>{this.getAll().forEach(e=>{e.onFocus()})})}
method onOnline (line 17) | onOnline(){Fn.batch(()=>{this.getAll().forEach(e=>{e.onOnline()})})}
method constructor (line 17) | constructor(e){super(),this.mutationId=e.mutationId,this.#t=e.mutationCa...
method setOptions (line 17) | setOptions(e){this.options=e,this.updateGcTime(this.options.gcTime)}
method meta (line 17) | get meta(){return this.options.meta}
method addObserver (line 17) | addObserver(e){this.#e.includes(e)||(this.#e.push(e),this.clearGcTimeout...
method removeObserver (line 17) | removeObserver(e){this.#e=this.#e.filter(t=>t!==e),this.scheduleGc(),thi...
method optionalRemove (line 17) | optionalRemove(){this.#e.length||(this.state.status==="pending"?this.sch...
method continue (line 17) | continue(){return this.#r?.continue()??this.execute(this.state.variables)}
method execute (line 17) | async execute(e){this.#r=Wk({fn:()=>this.options.mutationFn?this.options...
method #n (line 17) | #n(e){const t=n=>{switch(e.type){case"failed":return{...n,failureCount:e...
function Qk (line 17) | function Qk(){return{context:void 0,data:void 0,error:null,failureCount:...
method constructor (line 17) | constructor(e={}){super(),this.config=e,this.#e=new Map,this.#t=Date.now()}
method build (line 17) | build(e,t,n){const r=new UD({mutationCache:this,mutationId:++this.#t,opt...
method add (line 17) | add(e){const t=Df(e),n=this.#e.get(t)??[];n.push(e),this.#e.set(t,n),thi...
method remove (line 17) | remove(e){const t=Df(e);if(this.#e.has(t)){const n=this.#e.get(t)?.filte...
method canRun (line 17) | canRun(e){const t=this.#e.get(Df(e))?.find(n=>n.state.status==="pending"...
method runNext (line 17) | runNext(e){return this.#e.get(Df(e))?.find(n=>n!==e&&n.state.isPaused)?....
method clear (line 17) | clear(){Fn.batch(()=>{this.getAll().forEach(e=>{this.remove(e)})})}
method getAll (line 17) | getAll(){return[...this.#e.values()].flat()}
method find (line 17) | find(e){const t={exact:!0,...e};return this.getAll().find(n=>B0(t,n))}
method findAll (line 17) | findAll(e={}){return this.getAll().filter(t=>B0(e,t))}
method notify (line 17) | notify(e){Fn.batch(()=>{this.listeners.forEach(t=>{t(e)})})}
method resumePausedMutations (line 17) | resumePausedMutations(){const e=this.getAll().filter(t=>t.state.isPaused...
function Df (line 17) | function Df(e){return e.options.scope?.id??String(e.mutationId)}
function HD (line 17) | function HD(e){return{onFetch:(t,n)=>{const r=async()=>{const s=t.option...
function V0 (line 17) | function V0(e,{pages:t,pageParams:n}){const r=t.length-1;return t.length...
function qD (line 17) | function qD(e,{pages:t,pageParams:n}){return t.length>0?e.getPreviousPag...
method constructor (line 17) | constructor(e={}){this.#e=e.queryCache||new zD,this.#t=e.mutationCache||...
method mount (line 17) | mount(){this.#o++,this.#o===1&&(this.#s=Rb.subscribe(async e=>{e&&(await...
method unmount (line 17) | unmount(){this.#o--,this.#o===0&&(this.#s?.(),this.#s=void 0,this.#i?.()...
method isFetching (line 17) | isFetching(e){return this.#e.findAll({...e,fetchStatus:"fetching"}).length}
method isMutating (line 17) | isMutating(e){return this.#t.findAll({...e,status:"pending"}).length}
method getQueryData (line 17) | getQueryData(e){const t=this.defaultQueryOptions({queryKey:e});return th...
method ensureQueryData (line 17) | ensureQueryData(e){const t=this.getQueryData(e.queryKey);if(t===void 0)r...
method getQueriesData (line 17) | getQueriesData(e){return this.#e.findAll(e).map(({queryKey:t,state:n})=>...
method setQueryData (line 17) | setQueryData(e,t,n){const r=this.defaultQueryOptions({queryKey:e}),o=thi...
method setQueriesData (line 17) | setQueriesData(e,t,n){return Fn.batch(()=>this.#e.findAll(e).map(({query...
method getQueryState (line 17) | getQueryState(e){const t=this.defaultQueryOptions({queryKey:e});return t...
method removeQueries (line 17) | removeQueries(e){const t=this.#e;Fn.batch(()=>{t.findAll(e).forEach(n=>{...
method resetQueries (line 17) | resetQueries(e,t){const n=this.#e,r={type:"active",...e};return Fn.batch...
method cancelQueries (line 17) | cancelQueries(e={},t={}){const n={revert:!0,...t},r=Fn.batch(()=>this.#e...
method invalidateQueries (line 17) | invalidateQueries(e={},t={}){return Fn.batch(()=>{if(this.#e.findAll(e)....
method refetchQueries (line 17) | refetchQueries(e={},t){const n={...t,cancelRefetch:t?.cancelRefetch??!0}...
method fetchQuery (line 17) | fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.r...
method prefetchQuery (line 17) | prefetchQuery(e){return this.fetchQuery(e).then(ss).catch(ss)}
method fetchInfiniteQuery (line 17) | fetchInfiniteQuery(e){return e.behavior=HD(e.pages),this.fetchQuery(e)}
method prefetchInfiniteQuery (line 17) | prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ss).catc...
method resumePausedMutations (line 17) | resumePausedMutations(){return _p.isOnline()?this.#t.resumePausedMutatio...
method getQueryCache (line 17) | getQueryCache(){return this.#e}
method getMutationCache (line 17) | getMutationCache(){return this.#t}
method getDefaultOptions (line 17) | getDefaultOptions(){return this.#r}
method setDefaultOptions (line 17) | setDefaultOptions(e){this.#r=e}
method setQueryDefaults (line 17) | setQueryDefaults(e,t){this.#n.set(xi(e),{queryKey:e,defaultOptions:t})}
method getQueryDefaults (line 17) | getQueryDefaults(e){const t=[...this.#n.values()];let n={};return t.forE...
method setMutationDefaults (line 17) | setMutationDefaults(e,t){this.#a.set(xi(e),{mutationKey:e,defaultOptions...
method getMutationDefaults (line 17) | getMutationDefaults(e){const t=[...this.#a.values()];let n={};return t.f...
method defaultQueryOptions (line 17) | defaultQueryOptions(e){if(e._defaulted)return e;const t={...this.#r.quer...
method defaultMutationOptions (line 17) | defaultMutationOptions(e){return e?._defaulted?e:{...this.#r.mutations,....
method clear (line 17) | clear(){this.#e.clear(),this.#t.clear()}
method constructor (line 17) | constructor(e,t){super(),this.options=t,this.#e=e,this.#s=null,this.bind...
method bindMethods (line 17) | bindMethods(){this.refetch=this.refetch.bind(this)}
method onSubscribe (line 17) | onSubscribe(){this.listeners.size===1&&(this.#t.addObserver(this),H0(thi...
method onUnsubscribe (line 17) | onUnsubscribe(){this.hasListeners()||this.destroy()}
method shouldFetchOnReconnect (line 17) | shouldFetchOnReconnect(){return ky(this.#t,this.options,this.options.ref...
method shouldFetchOnWindowFocus (line 17) | shouldFetchOnWindowFocus(){return ky(this.#t,this.options,this.options.r...
method destroy (line 17) | destroy(){this.listeners=new Set,this.#b(),this.#x(),this.#t.removeObser...
method setOptions (line 17) | setOptions(e,t){const n=this.options,r=this.#t;if(this.options=this.#e.d...
method getOptimisticResult (line 17) | getOptimisticResult(e){const t=this.#e.getQueryCache().build(this.#e,e),...
method getCurrentResult (line 17) | getCurrentResult(){return this.#n}
method trackResult (line 17) | trackResult(e,t){const n={};return Object.keys(e).forEach(r=>{Object.def...
method trackProp (line 17) | trackProp(e){this.#h.add(e)}
method getCurrentQuery (line 17) | getCurrentQuery(){return this.#t}
method refetch (line 17) | refetch({...e}={}){return this.fetch({...e})}
method fetchOptimistic (line 17) | fetchOptimistic(e){const t=this.#e.defaultQueryOptions(e),n=this.#e.getQ...
method fetch (line 17) | fetch(e){return this.#d({...e,cancelRefetch:e.cancelRefetch??!0}).then((...
method #d (line 17) | #d(e){this.#w();let t=this.#t.fetch(this.options,e);return e?.throwOnErr...
method #g (line 17) | #g(){this.#b();const e=_l(this.options.staleTime,this.#t);if(Fl||this.#n...
method #m (line 17) | #m(){return(typeof this.options.refetchInterval=="function"?this.options...
method #v (line 17) | #v(e){this.#x(),this.#l=e,!(Fl||ws(this.options.enabled,this.#t)===!1||!...
method #y (line 17) | #y(){this.#g(),this.#v(this.#m())}
method #b (line 17) | #b(){this.#c&&(clearTimeout(this.#c),this.#c=void 0)}
method #x (line 17) | #x(){this.#u&&(clearInterval(this.#u),this.#u=void 0)}
method createResult (line 17) | createResult(e,t){const n=this.#t,r=this.options,s=this.#n,o=this.#a,l=t...
method updateResult (line 17) | updateResult(e){const t=this.#n,n=this.createResult(this.#t,this.options...
method #w (line 17) | #w(){const e=this.#e.getQueryCache().build(this.#e,this.options);if(e===...
method onQueryUpdate (line 17) | onQueryUpdate(){this.updateResult(),this.hasListeners()&&this.#y()}
method #S (line 17) | #S(e){Fn.batch(()=>{e.listeners&&this.listeners.forEach(t=>{t(this.#n)})...
function GD (line 17) | function GD(e,t){return ws(t.enabled,e)!==!1&&e.state.data===void 0&&!(e...
function H0 (line 17) | function H0(e,t){return GD(e,t)||e.state.data!==void 0&&ky(e,t,t.refetch...
function ky (line 17) | function ky(e,t,n){if(ws(t.enabled,e)!==!1){const r=typeof n=="function"...
function q0 (line 17) | function q0(e,t,n,r){return(e!==t||ws(r.enabled,e)===!1)&&(!n.suspense||...
function Pb (line 17) | function Pb(e,t){return ws(t.enabled,e)!==!1&&e.isStaleByTime(_l(t.stale...
function JD (line 17) | function JD(e,t){return!Mp(e.getCurrentResult(),t)}
method constructor (line 17) | constructor(t,n){super(),this.#e=t,this.setOptions(n),this.bindMethods()...
method bindMethods (line 17) | bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.b...
method setOptions (line 17) | setOptions(t){const n=this.options;this.options=this.#e.defaultMutationO...
method onUnsubscribe (line 17) | onUnsubscribe(){this.hasListeners()||this.#r?.removeObserver(this)}
method onMutationUpdate (line 17) | onMutationUpdate(t){this.#a(),this.#o(t)}
method getCurrentResult (line 17) | getCurrentResult(){return this.#t}
method reset (line 17) | reset(){this.#r?.removeObserver(this),this.#r=void 0,this.#a(),this.#o()}
method mutate (line 17) | mutate(t,n){return this.#n=n,this.#r?.removeObserver(this),this.#r=this....
method #a (line 17) | #a(){const t=this.#r?.state??Qk();this.#t={...t,isPending:t.status==="pe...
method #o (line 17) | #o(t){Fn.batch(()=>{if(this.#n&&this.hasListeners()){const n=this.#t.var...
function YD (line 17) | function YD(){let e=!1;return{clearReset:()=>{e=!1},reset:()=>{e=!0},isR...
function ej (line 17) | function ej(e,t){return typeof e=="function"?e(...t):!!e}
function tF (line 17) | function tF(){}
function lF (line 17) | function lF(e,t,n){const r=Ob(),s=ZD(),o=eF(),l=r.defaultQueryOptions(e)...
function mt (line 17) | function mt(e,t){return lF(e,WD)}
function cF (line 17) | function cF(e,t){const n=Ob(),[r]=y.useState(()=>new QD(n,e));y.useEffec...
function uF (line 25) | function uF(){return K0||(K0=1,(function(e){function t(H,q){var he=H.len...
function dF (line 25) | function dF(){return W0||(W0=1,uv.exports=uF()),uv.exports}
function fF (line 33) | function fF(){if(G0)return Cr;G0=1;var e=pd(),t=dF();function n(a){for(v...
function tj (line 40) | function tj(){if(J0)return cv.exports;J0=1;function e(){if(!(typeof __RE...
function pF (line 40) | function pF(){if(Q0)return Ff;Q0=1;var e=tj();return Ff.createRoot=e.cre...
method init (line 40) | init(e){CF(e.options.react),kF(e)}
class NF (line 40) | class NF{constructor(){this.usedNamespaces={}}addUsedNamespaces(t){t.for...
method constructor (line 40) | constructor(){this.usedNamespaces={}}
method addUsedNamespaces (line 40) | addUsedNamespaces(t){t.forEach(n=>{this.usedNamespaces[n]??=!0})}
method getUsedNamespaces (line 40) | getUsedNamespaces(){return Object.keys(this.usedNamespaces)}
function RF (line 40) | function RF({i18n:e,defaultNS:t,children:n}){const r=y.useMemo(()=>({i18...
function mn (line 49) | function mn(){return mn=Object.assign?Object.assign.bind():function(e){f...
function OF (line 49) | function OF(e){e===void 0&&(e={});function t(r,s){let{pathname:o,search:...
function Ct (line 49) | function Ct(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}
function Ll (line 49) | function Ll(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw ne...
function IF (line 49) | function IF(){return Math.random().toString(36).substr(2,8)}
function tC (line 49) | function tC(e,t){return{usr:e.state,key:e.key,idx:t}}
function Iu (line 49) | function Iu(e,t,n,r){return n===void 0&&(n=null),mn({pathname:typeof e==...
function wi (line 49) | function wi(e){let{pathname:t="/",search:n="",hash:r=""}=e;return n&&n!=...
function _a (line 49) | function _a(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.subst...
function AF (line 49) | function AF(e,t,n,r){r===void 0&&(r={});let{window:s=document.defaultVie...
function FF (line 49) | function FF(e){return e.index===!0}
function Au (line 49) | function Au(e,t,n,r){return n===void 0&&(n=[]),r===void 0&&(r={}),e.map(...
function oi (line 49) | function oi(e,t,n){return n===void 0&&(n="/"),cp(e,t,n,!1)}
function cp (line 49) | function cp(e,t,n,r){let s=typeof t=="string"?_a(t):t,o=Xl(s.pathname||"...
function LF (line 49) | function LF(e,t){let{route:n,pathname:r,params:s}=e;return{id:n.id,pathn...
function aj (line 49) | function aj(e,t,n,r){t===void 0&&(t=[]),n===void 0&&(n=[]),r===void 0&&(...
function ij (line 49) | function ij(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t...
function $F (line 49) | function $F(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:WF(t.rout...
function KF (line 49) | function KF(e,t){let n=e.split("/"),r=n.length;return n.some(nC)&&(r+=qF...
function WF (line 49) | function WF(e,t){return e.length===t.length&&e.slice(0,-1).every((r,s)=>...
function GF (line 49) | function GF(e,t,n){n===void 0&&(n=!1);let{routesMeta:r}=e,s={},o="/",l=[...
function rC (line 49) | function rC(e,t){typeof e=="string"&&(e={path:e,caseSensitive:!1,end:!0}...
function JF (line 49) | function JF(e,t,n){t===void 0&&(t=!1),n===void 0&&(n=!0),Ll(e==="*"||!e....
function QF (line 49) | function QF(e){try{return e.split("/").map(t=>decodeURIComponent(t).repl...
function Xl (line 49) | function Xl(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.to...
function ZF (line 49) | function ZF(e,t){t===void 0&&(t="/");let{pathname:n,search:r="",hash:s="...
function YF (line 49) | function YF(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/...
function fv (line 49) | function fv(e,t,n,r){return"Cannot include a '"+e+"' character in a manu...
function lj (line 49) | function lj(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path....
function hh (line 49) | function hh(e,t){let n=lj(e);return t?n.map((r,s)=>s===n.length-1?r.path...
function gh (line 49) | function gh(e,t,n,r){r===void 0&&(r=!1);let s;typeof e=="string"?s=_a(e)...
class Ab (line 49) | class Ab{constructor(t,n,r,s){s===void 0&&(s=!1),this.status=t,this.stat...
method constructor (line 49) | constructor(t,n,r,s){s===void 0&&(s=!1),this.status=t,this.statusText=...
function mh (line 49) | function mh(e){return e!=null&&typeof e.status=="number"&&typeof e.statu...
function c2 (line 49) | function c2(e){const t=e.window?e.window:typeof window<"u"?window:void 0...
function u2 (line 49) | function u2(e){return e!=null&&("formData"in e&&e.formData!=null||"body"...
function Ny (line 49) | function Ny(e,t,n,r,s,o,l,u){let d,f;if(l){d=[];for(let m of t)if(d.push...
function sC (line 49) | function sC(e,t,n,r){if(!r||!u2(r))return{path:n};if(r.formMethod&&!E2(r...
function d2 (line 50) | function d2(e,t){let n=e;if(t){let r=e.findIndex(s=>s.route.id===t);r>=0...
function oC (line 50) | function oC(e,t,n,r,s,o,l,u,d,f,h,m,g,x,b,w){let C=w?Br(w[1])?w[1].error...
function f2 (line 50) | function f2(e,t,n){let r=!t||n.route.id!==t.route.id,s=e[n.route.id]===v...
function dj (line 50) | function dj(e,t){let n=e.route.path;return e.pathname!==t.pathname||n!=n...
function aC (line 50) | function aC(e,t){if(e.route.shouldRevalidate){let n=e.route.shouldRevali...
function p2 (line 50) | async function p2(e,t,n,r,s,o,l,u){let d=[t,...n.map(f=>f.route.id)].joi...
function fj (line 50) | function fj(e,t,n,r,s){if(e){var o;let l=r[e];Ct(l,"No route found to pa...
function iC (line 50) | async function iC(e,t,n){if(!e.lazy)return;let r=await e.lazy();if(!e.la...
function h2 (line 50) | function h2(e){return Promise.all(e.matches.map(t=>t.resolve()))}
function g2 (line 50) | async function g2(e,t,n,r,s,o,l,u){let d=r.reduce((m,g)=>m.add(g.route.i...
function m2 (line 50) | async function m2(e,t,n,r,s,o,l){let u,d,f=h=>{let m,g=new Promise((w,C)...
function v2 (line 50) | async function v2(e){let{result:t,type:n,status:r}=e;if(hj(t)){let l;try...
function y2 (line 50) | function y2(e,t,n,r,s,o){let l=e.headers.get("Location");if(Ct(l,"Redire...
function lC (line 50) | function lC(e,t,n){if(Db.test(e)){let r=e,s=r.startsWith("//")?new URL(t...
function fl (line 50) | function fl(e,t,n,r){let s=e.createURL(pj(t)).toString(),o={signal:n};if...
function My (line 50) | function My(e){let t=new URLSearchParams;for(let[n,r]of e.entries())t.ap...
function cC (line 50) | function cC(e){let t=new FormData;for(let[n,r]of e.entries())t.append(n,...
function b2 (line 50) | function b2(e,t,n,r,s,o){let l={},u=null,d,f=!1,h={},m=r&&Br(r[1])?r[1]....
function uC (line 50) | function uC(e,t,n,r,s,o,l,u){let{loaderData:d,errors:f}=b2(t,n,r,s,u);fo...
function dC (line 50) | function dC(e,t,n,r){let s=mn({},t);for(let o of n){let l=o.route.id;if(...
function fC (line 50) | function fC(e){return e?Br(e[1])?{actionData:{}}:{actionData:{[e[0]]:e[1...
function jl (line 50) | function jl(e,t){return(t?e.slice(0,e.findIndex(r=>r.route.id===t)+1):[....
function pC (line 50) | function pC(e){let t=e.length===1?e[0]:e.find(n=>n.index||!n.path||n.pat...
function lr (line 50) | function lr(e,t){let{pathname:n,routeId:r,method:s,type:o,message:l}=t==...
function hC (line 51) | function hC(e){for(let t=e.length-1;t>=0;t--){let n=e[t];if(ii(n))return...
function pj (line 51) | function pj(e){let t=typeof e=="string"?_a(e):e;return wi(mn({},t,{hash:...
function x2 (line 51) | function x2(e,t){return e.pathname!==t.pathname||e.search!==t.search?!1:...
function w2 (line 51) | function w2(e){return typeof e=="object"&&e!=null&&"then"in e}
function S2 (line 51) | function S2(e){return hj(e.result)&&o2.has(e.result.status)}
function ai (line 51) | function ai(e){return e.type===Zt.deferred}
function Br (line 51) | function Br(e){return e.type===Zt.error}
function ii (line 51) | function ii(e){return(e&&e.type)===Zt.redirect}
function C2 (line 51) | function C2(e){let t=e;return t&&typeof t=="object"&&typeof t.data=="obj...
function hj (line 51) | function hj(e){return e!=null&&typeof e.status=="number"&&typeof e.statu...
function E2 (line 51) | function E2(e){return s2.has(e.toLowerCase())}
function bs (line 51) | function bs(e){return n2.has(e.toLowerCase())}
function gC (line 51) | async function gC(e,t,n,r,s,o){for(let l=0;l<n.length;l++){let u=n[l],d=...
function gj (line 51) | async function gj(e,t,n){if(n===void 0&&(n=!1),!await e.deferredData.res...
function Fb (line 51) | function Fb(e){return new URLSearchParams(e).getAll("index").some(t=>t==...
function gu (line 51) | function gu(e,t){let n=typeof t=="string"?_a(t).search:t.search;if(e[e.l...
function mC (line 51) | function mC(e){let{formMethod:t,formAction:n,formEncType:r,text:s,formDa...
function hv (line 51) | function hv(e,t){return t?{state:"loading",location:e,formMethod:t.formM...
function k2 (line 51) | function k2(e,t){return{state:"submitting",location:e,formMethod:t.formM...
function tu (line 51) | function tu(e,t){return e?{state:"loading",formMethod:e.formMethod,formA...
function j2 (line 51) | function j2(e,t){return{state:"submitting",formMethod:e.formMethod,formA...
function da (line 51) | function da(e){return{state:"idle",formMethod:void 0,formAction:void 0,f...
function T2 (line 51) | function T2(e,t){try{let n=e.sessionStorage.getItem(uj);if(n){let r=JSON...
function N2 (line 51) | function N2(e,t){if(t.size>0){let n={};for(let[r,s]of t)n[r]=[...s];try{...
function Rp (line 60) | function Rp(){return Rp=Object.assign?Object.assign.bind():function(e){f...
function M2 (line 60) | function M2(e,t){let{relative:n}=t===void 0?{}:t;ec()||Ct(!1);let{basena...
function ec (line 60) | function ec(){return y.useContext(Lb)!=null}
function Pi (line 60) | function Pi(){return ec()||Ct(!1),y.useContext(Lb).location}
function yj (line 60) | function yj(e){y.useContext(Ra).static||y.useLayoutEffect(e)}
function dn (line 60) | function dn(){let{isDataRoute:e}=y.useContext(Po);return e?z2():_2()}
function _2 (line 60) | function _2(){ec()||Ct(!1);let e=y.useContext(vh),{basename:t,future:n,n...
function ls (line 60) | function ls(){let{matches:e}=y.useContext(Po),t=e[e.length-1];return t?t...
function bj (line 60) | function bj(e,t){let{relative:n}=t===void 0?{}:t,{future:r}=y.useContext...
function R2 (line 60) | function R2(e,t,n,r){ec()||Ct(!1);let{navigator:s}=y.useContext(Ra),{mat...
function P2 (line 60) | function P2(){let e=B2(),t=mh(e)?e.status+" "+e.statusText:e instanceof ...
class I2 (line 60) | class I2 extends y.Component{constructor(t){super(t),this.state={locatio...
method constructor (line 60) | constructor(t){super(t),this.state={location:t.location,revalidation:t...
method getDerivedStateFromError (line 60) | static getDerivedStateFromError(t){return{error:t}}
method getDerivedStateFromProps (line 60) | static getDerivedStateFromProps(t,n){return n.location!==t.location||n...
method componentDidCatch (line 60) | componentDidCatch(t,n){console.error("React Router caught the followin...
method render (line 60) | render(){return this.state.error!==void 0?y.createElement(Po.Provider,...
function A2 (line 60) | function A2(e){let{routeContext:t,match:n,children:r}=e,s=y.useContext(v...
function D2 (line 60) | function D2(e,t,n,r){var s;if(t===void 0&&(t=[]),n===void 0&&(n=null),r=...
function F2 (line 60) | function F2(e){let t=y.useContext(vh);return t||Ct(!1),t}
function L2 (line 60) | function L2(e){let t=y.useContext(mj);return t||Ct(!1),t}
function $2 (line 60) | function $2(e){let t=y.useContext(Po);return t||Ct(!1),t}
function Sj (line 60) | function Sj(e){let t=$2(),n=t.matches[t.matches.length-1];return n.route...
function B2 (line 60) | function B2(){var e;let t=y.useContext(vj),n=L2(wj.UseRouteError),r=Sj()...
function z2 (line 60) | function z2(){let{router:e}=F2(xj.UseNavigateStable),t=Sj(),n=y.useRef(!...
function U2 (line 60) | function U2(e,t,n){vC[e]||(vC[e]=!0)}
function Cj (line 60) | function Cj(e){let{to:t,replace:n,state:r,relative:s}=e;ec()||Ct(!1);let...
function V2 (line 60) | function V2(e){let{basename:t="/",children:n=null,location:r,navigationT...
function H2 (line 60) | function H2(e){let t={hasErrorBoundary:e.ErrorBoundary!=null||e.errorEle...
function Du (line 69) | function Du(){return Du=Object.assign?Object.assign.bind():function(e){f...
function q2 (line 69) | function q2(e,t){if(e==null)return{};var n={},r=Object.keys(e),s,o;for(o...
function K2 (line 69) | function K2(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}
function W2 (line 69) | function W2(e,t){return e.button===0&&(!t||t==="_self")&&!K2(e)}
function _y (line 69) | function _y(e){return e===void 0&&(e=""),new URLSearchParams(typeof e=="...
function G2 (line 69) | function G2(e,t){let n=_y(e);return t&&t.forEach((r,s)=>{n.has(s)||t.get...
function Z2 (line 69) | function Z2(e,t){return c2({basename:void 0,future:Du({},void 0,{v7_prep...
function Y2 (line 69) | function Y2(){var e;let t=(e=window)==null?void 0:e.__staticRouterHydrat...
function X2 (line 69) | function X2(e){if(!e)return null;let t=Object.entries(e),n={};for(let[r,...
function sL (line 69) | function sL(e){yC?yC(e):e()}
function nu (line 69) | function nu(e){bC?bC(e):e()}
class oL (line 69) | class oL{constructor(){this.status="pending",this.promise=new Promise((t...
method constructor (line 69) | constructor(){this.status="pending",this.promise=new Promise((t,n)=>{t...
function aL (line 69) | function aL(e){let{fallbackElement:t,router:n,future:r}=e,[s,o]=y.useSta...
function lL (line 69) | function lL(e){let{routes:t,future:n,state:r}=e;return R2(t,void 0,r,n)}
function j (line 69) | function j(M){r&&r(M),M.defaultPrevented||k(M)}
function dL (line 69) | function dL(e,t){let{target:n,replace:r,state:s,preventScrollReset:o,rel...
function hd (line 69) | function hd(e){let t=y.useRef(_y(e)),n=y.useRef(!1),r=Pi(),s=y.useMemo((...
function Ej (line 69) | function Ej(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+...
function wo (line 69) | function wo(){for(var e,t,n=0,r="",s=arguments.length;n<s;n++)(e=argumen...
function fL (line 69) | function fL(e,t,n){n===void 0&&(n=300);const{scrollHeight:r,style:s}=e;r...
function yh (line 69) | function yh(e){let{enter:t,exit:n,appendPosition:r=!1,collapse:s=!0,coll...
function SC (line 69) | function SC(e,t){return e!=null?{content:e.content,containerId:e.props.c...
function jj (line 69) | function jj(e,t){var n;if(t)return!((n=ur.get(t))==null||!n.isToastActiv...
function Tj (line 69) | function Tj(e,t){Ry(e)&&(kj()||$u.push({content:e,options:t}),ur.forEach...
function CC (line 69) | function CC(e,t){ur.forEach(n=>{t!=null&&t!=null&&t.containerId?t?.conta...
function hL (line 69) | function hL(e){const{subscribe:t,getSnapshot:n,setProps:r}=y.useRef((fun...
function gL (line 69) | function gL(e){const[t,n]=y.useState(!1),[r,s]=y.useState(!1),o=y.useRef...
function mL (line 69) | function mL(e){let{delay:t,isRunning:n,closeToast:r,type:s="default",hid...
function yL (line 69) | function yL(e){return e&&(pi(e.toastId)||Lu(e.toastId))?e.toastId:Nj()}
function ku (line 69) | function ku(e,t){return Tj(e,t),t.toastId}
function Pp (line 69) | function Pp(e,t){return{...t,type:t&&t.type||e,toastId:yL(t)}}
function Lf (line 69) | function Lf(e){return(t,n)=>ku(t,Pp(e,n))}
function me (line 69) | function me(e,t){return ku(e,Pp("default",t))}
function CL (line 69) | function CL(e){let t={...SL,...e};const n=e.stacked,[r,s]=y.useState(!0)...
function kL (line 69) | function kL({children:e,defaultTheme:t="system",storageKey:n="vite-ui-th...
method retry (line 69) | retry(e){return e>=3?(mv===!1&&(mv=!0,me.error("The application is takin...
function Oj (line 69) | function Oj(e,t){return function(){return e.apply(t,arguments)}}
function gd (line 69) | function gd(e){return e!==null&&!$l(e)&&e.constructor!==null&&!$l(e.cons...
function NL (line 69) | function NL(e){let t;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?t...
function vd (line 69) | function vd(e,t,{allOwnKeys:n=!1}={}){if(e===null||typeof e>"u")return;l...
function Fj (line 69) | function Fj(e,t){if(gd(e))return null;t=t.toLowerCase();const n=Object.k...
function Oy (line 69) | function Oy(){const{caseless:e,skipUndefined:t}=Lj(this)&&this||{},n={},...
function a4 (line 69) | function a4(e){return!!(e&&jr(e.append)&&e[Ij]==="FormData"&&e[xh])}
function vt (line 69) | function vt(e,t,n,r,s){Error.call(this),Error.captureStackTrace?Error.ca...
function Iy (line 69) | function Iy(e){return ce.isPlainObject(e)||ce.isArray(e)}
function Vj (line 69) | function Vj(e){return ce.endsWith(e,"[]")?e.slice(0,-2):e}
function kC (line 69) | function kC(e,t,n){return e?e.concat(t).map(function(s,o){return s=Vj(s)...
function p4 (line 69) | function p4(e){return ce.isArray(e)&&!e.some(Iy)}
function Ch (line 69) | function Ch(e,t,n){if(!ce.isObject(e))throw new TypeError("target must b...
function jC (line 69) | function jC(e){const t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E...
function Bb (line 69) | function Bb(e,t){this._pairs=[],e&&Ch(e,this,t)}
function g4 (line 69) | function g4(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace...
function qj (line 69) | function qj(e,t,n){if(!t)return e;const r=n&&n.encode||g4;ce.isFunction(...
class TC (line 69) | class TC{constructor(){this.handlers=[]}use(t,n,r){return this.handlers....
method constructor (line 69) | constructor(){this.handlers=[]}
method use (line 69) | use(t,n,r){return this.handlers.push({fulfilled:t,rejected:n,synchrono...
method eject (line 69) | eject(t){this.handlers[t]&&(this.handlers[t]=null)}
method clear (line 69) | clear(){this.handlers&&(this.handlers=[])}
method forEach (line 69) | forEach(t){ce.forEach(this.handlers,function(r){r!==null&&t(r)})}
function E4 (line 69) | function E4(e,t){return Ch(e,new rr.classes.URLSearchParams,{visitor:fun...
function k4 (line 69) | function k4(e){return ce.matchAll(/\w+|\[(\w*)]/g,e).map(t=>t[0]==="[]"?...
function j4 (line 69) | function j4(e){const t={},n=Object.keys(e);let r;const s=n.length;let o;...
function Wj (line 69) | function Wj(e){function t(n,r,s,o){let l=n[o++];if(l==="__proto__")retur...
function T4 (line 69) | function T4(e,t,n){if(ce.isString(e))try{return(t||JSON.parse)(e),ce.tri...
function ru (line 70) | function ru(e){return e&&String(e).trim().toLowerCase()}
function fp (line 70) | function fp(e){return e===!1||e==null?e:ce.isArray(e)?e.map(fp):String(e)}
function _4 (line 70) | function _4(e){const t=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;...
function vv (line 70) | function vv(e,t,n,r,s){if(ce.isFunction(r))return r.call(this,t,n);if(s&...
function P4 (line 70) | function P4(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(...
function O4 (line 70) | function O4(e,t){const n=ce.toCamelCase(" "+t);["get","set","has"].forEa...
method constructor (line 70) | constructor(t){t&&this.set(t)}
method set (line 70) | set(t,n,r){const s=this;function o(u,d,f){const h=ru(d);if(!h)throw new ...
method get (line 70) | get(t,n){if(t=ru(t),t){const r=ce.findKey(this,t);if(r){const s=this[r];...
method has (line 70) | has(t,n){if(t=ru(t),t){const r=ce.findKey(this,t);return!!(r&&this[r]!==...
method delete (line 70) | delete(t,n){const r=this;let s=!1;function o(l){if(l=ru(l),l){const u=ce...
method clear (line 70) | clear(t){const n=Object.keys(this);let r=n.length,s=!1;for(;r--;){const ...
method normalize (line 70) | normalize(t){const n=this,r={};return ce.forEach(this,(s,o)=>{const l=ce...
method concat (line 70) | concat(...t){return this.constructor.concat(this,...t)}
method toJSON (line 70) | toJSON(t){const n=Object.create(null);return ce.forEach(this,(r,s)=>{r!=...
method [Symbol.iterator] (line 70) | [Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator...
method toString (line 70) | toString(){return Object.entries(this.toJSON()).map(([t,n])=>t+": "+n).j...
method getSetCookie (line 71) | getSetCookie(){return this.get("set-cookie")||[]}
method [Symbol.toStringTag] (line 71) | get[Symbol.toStringTag](){return"AxiosHeaders"}
method from (line 71) | static from(t){return t instanceof this?t:new this(t)}
method concat (line 71) | static concat(t,...n){const r=new this(t);return n.forEach(s=>r.set(s)),r}
method accessor (line 71) | static accessor(t){const r=(this[NC]=this[NC]={accessors:{}}).accessors,...
method set (line 71) | set(r){this[n]=r}
function yv (line 71) | function yv(e,t){const n=this||yd,r=t||n,s=Tr.from(r.headers);let o=r.da...
function Gj (line 71) | function Gj(e){return!!(e&&e.__CANCEL__)}
function rc (line 71) | function rc(e,t,n){vt.call(this,e??"canceled",vt.ERR_CANCELED,t,n),this....
function Jj (line 71) | function Jj(e,t,n){const r=n.config.validateStatus;!n.status||!r||r(n.st...
function I4 (line 71) | function I4(e){const t=/^([-+\w]{1,25})(:?\/\/|:)/.exec(e);return t&&t[1...
function A4 (line 71) | function A4(e,t){e=e||10;const n=new Array(e),r=new Array(e);let s=0,o=0...
function D4 (line 71) | function D4(e,t){let n=0,r=1e3/t,s,o;const l=(f,h=Date.now())=>{n=h,s=nu...
method write (line 71) | write(e,t,n,r,s,o){const l=[e+"="+encodeURIComponent(t)];ce.isNumber(n)&...
method read (line 71) | read(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]...
method remove (line 71) | remove(e){this.write(e,"",Date.now()-864e5)}
method write (line 71) | write(){}
method read (line 71) | read(){return null}
method remove (line 71) | remove(){}
function $4 (line 71) | function $4(e){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(e)}
function B4 (line 71) | function B4(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""...
function Qj (line 71) | function Qj(e,t,n){let r=!$4(t);return e&&(r||n==!1)?B4(e,t):t}
function Si (line 71) | function Si(e,t){t=t||{};const n={};function r(f,h,m,g){return ce.isPlai...
function w (line 71) | function w(){x&&x(),b&&b(),s.cancelToken&&s.cancelToken.unsubscribe(h),s...
function k (line 71) | function k(){if(!C)return;const M=Tr.from("getAllResponseHeaders"in C&&C...
method pull (line 71) | async pull(d){try{const{done:f,value:h}=await s.next();if(f){u(),d.close...
method cancel (line 71) | cancel(d){return u(d),s.return()}
method duplex (line 71) | get duplex(){return b=!0,"half"}
function bv (line 73) | function bv(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.sign...
function LC (line 73) | function LC(e){return bv(e),e.headers=Tr.from(e.headers),e.data=yv.call(...
function s (line 73) | function s(o,l){return"[Axios v"+eT+"] Transitional option '"+o+"'"+l+(r...
function Z4 (line 73) | function Z4(e,t,n){if(typeof e!="object")throw new vt("options must be a...
method constructor (line 73) | constructor(t){this.defaults=t||{},this.interceptors={request:new TC,res...
method request (line 73) | async request(t,n){try{return await this._request(t,n)}catch(r){if(r ins...
method _request (line 74) | _request(t,n){typeof t=="string"?(n=n||{},n.url=t):n=t||{},n=Si(this.def...
method getUri (line 74) | getUri(t){t=Si(this.defaults,t);const n=Qj(t.baseURL,t.url,t.allowAbsolu...
function n (line 74) | function n(r){return function(o,l,u){return this.request(Si(u||{},{metho...
method constructor (line 74) | constructor(t){if(typeof t!="function")throw new TypeError("executor mus...
method throwIfRequested (line 74) | throwIfRequested(){if(this.reason)throw this.reason}
method subscribe (line 74) | subscribe(t){if(this.reason){t(this.reason);return}this._listeners?this....
method unsubscribe (line 74) | unsubscribe(t){if(!this._listeners)return;const n=this._listeners.indexO...
method toAbortSignal (line 74) | toAbortSignal(){const t=new AbortController,n=r=>{t.abort(r)};return thi...
method source (line 74) | static source(){let t;return{token:new tT(function(s){t=s}),cancel:t}}
function X4 (line 74) | function X4(e){return function(n){return e.apply(null,n)}}
function e$ (line 74) | function e$(e){return ce.isObject(e)&&e.isAxiosError===!0}
function nT (line 74) | function nT(e){const t=new hi(e),n=Oj(hi.prototype.request,t);return ce....
function r$ (line 74) | function r$(e,t){typeof e=="function"?e(t):e!=null&&(e.current=t)}
function kh (line 74) | function kh(...e){return t=>e.forEach(n=>r$(n,t))}
function Rt (line 74) | function Rt(...e){return y.useCallback(kh(...e),e)}
function o$ (line 74) | function o$(e){return y.isValidElement(e)&&e.type===s$}
function a$ (line 74) | function a$(e,t){const n={...t};for(const r in t){const s=e[r],o=t[r];/^...
function i$ (line 74) | function i$(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get...
function oT (line 74) | function oT(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+...
function l$ (line 74) | function l$(){for(var e,t,n=0,r="";n<arguments.length;)(e=arguments[n++]...
function c$ (line 74) | function c$(e){const t=d$(e),{conflictingClassGroups:n,conflictingClassG...
function aT (line 74) | function aT(e,t){if(e.length===0)return t.classGroupId;const n=e[0],r=t....
function u$ (line 74) | function u$(e){if(UC.test(e)){const t=UC.exec(e)[1],n=t?.substring(0,t.i...
function d$ (line 74) | function d$(e){const{theme:t,prefix:n}=e,r={nextPart:new Map,validators:...
function $y (line 74) | function $y(e,t,n,r){e.forEach(s=>{if(typeof s=="string"){const o=s===""...
function VC (line 74) | function VC(e,t){let n=e;return t.split(Ub).forEach(r=>{n.nextPart.has(r...
function f$ (line 74) | function f$(e){return e.isThemeGetter}
function p$ (line 74) | function p$(e,t){return t?e.map(([n,r])=>{const s=r.map(o=>typeof o=="st...
function h$ (line 74) | function h$(e){if(e<1)return{get:()=>{},set:()=>{}};let t=0,n=new Map,r=...
function g$ (line 74) | function g$(e){const{separator:t,experimentalParseClassName:n}=e,r=t.len...
function m$ (line 74) | function m$(e){if(e.length<=1)return e;const t=[];let n=[];return e.forE...
function v$ (line 74) | function v$(e){return{cache:h$(e.cacheSize),parseClassName:g$(e),...c$(e)}}
function b$ (line 74) | function b$(e,t){const{parseClassName:n,getClassGroupId:r,getConflicting...
function x$ (line 74) | function x$(){let e=0,t,n,r="";for(;e<arguments.length;)(t=arguments[e++...
function lT (line 74) | function lT(e){if(typeof e=="string")return e;let t,n="";for(let r=0;r<e...
function w$ (line 74) | function w$(e,...t){let n,r,s,o=l;function l(d){const f=t.reduce((h,m)=>...
function nn (line 74) | function nn(e){const t=n=>n[e]||[];return t.isThemeGetter=!0,t}
function ho (line 74) | function ho(e){return ci(e)||C$.has(e)||S$.test(e)}
function ca (line 74) | function ca(e){return sc(e,"length",D$)}
function ci (line 74) | function ci(e){return!!e&&!Number.isNaN(Number(e))}
function zf (line 74) | function zf(e){return sc(e,"number",ci)}
function su (line 74) | function su(e){return!!e&&Number.isInteger(Number(e))}
function M$ (line 74) | function M$(e){return e.endsWith("%")&&ci(e.slice(0,-1))}
function xt (line 74) | function xt(e){return cT.test(e)}
function ua (line 74) | function ua(e){return E$.test(e)}
function R$ (line 74) | function R$(e){return sc(e,_$,uT)}
function P$ (line 74) | function P$(e){return sc(e,"position",uT)}
function I$ (line 74) | function I$(e){return sc(e,O$,L$)}
function A$ (line 74) | function A$(e){return sc(e,"",F$)}
function ou (line 74) | function ou(){return!0}
function sc (line 74) | function sc(e,t,n){const r=cT.exec(e);return r?r[1]?typeof t=="string"?r...
function D$ (line 74) | function D$(e){return k$.test(e)&&!j$.test(e)}
function uT (line 74) | function uT(){return!1}
function F$ (line 74) | function F$(e){return T$.test(e)}
function L$ (line 74) | function L$(e){return N$.test(e)}
function $$ (line 74) | function $$(){const e=nn("colors"),t=nn("spacing"),n=nn("blur"),r=nn("br...
function Ie (line 74) | function Ie(...e){return B$(wo(e))}
function Vb (line 74) | function Vb(){const{t:e}=Ve(),t=dr(jn.API_URL),{data:n}=n$({url:t}),r=y....
function Ue (line 389) | function Ue(e,t,{checkForDefaultPrevented:n=!0}={}){return function(s){i...
function _B (line 389) | function _B(e,t){const n=y.createContext(t);function r(o){const{children...
function us (line 389) | function us(e,t=[]){let n=[];function r(o,l){const u=y.createContext(l),...
function RB (line 389) | function RB(...e){const t=e[0];if(e.length===1)return t;const n=()=>{con...
function Rn (line 389) | function Rn(e){const t=y.useRef(e);return y.useEffect(()=>{t.current=e})...
function ya (line 389) | function ya({prop:e,defaultProp:t,onChange:n=()=>{}}){const[r,s]=PB({def...
function PB (line 389) | function PB({defaultProp:e,onChange:t}){const n=y.useState(e),[r]=n,s=y....
function yT (line 389) | function yT(e,t){e&&Ma.flushSync(()=>e.dispatchEvent(t))}
function Kb (line 389) | function Kb(e){const t=e+"CollectionProvider",[n,r]=us(t),[s,o]=n(t,{col...
function xd (line 389) | function xd(e){const t=y.useContext(IB);return e||t||"ltr"}
function AB (line 389) | function AB(e,t=globalThis?.document){const n=Rn(e);y.useEffect(()=>{con...
function zB (line 389) | function zB(e,t=globalThis?.document){const n=Rn(e),r=y.useRef(!1),s=y.u...
function UB (line 389) | function UB(e,t=globalThis?.document){const n=Rn(e),r=y.useRef(!1);retur...
function KC (line 389) | function KC(){const e=new CustomEvent(By);document.dispatchEvent(e)}
function xT (line 389) | function xT(e,t,n,{discrete:r}){const s=n.originalEvent.target,o=new Cus...
function Wb (line 389) | function Wb(){y.useEffect(()=>{const e=document.querySelectorAll("[data-...
function WC (line 389) | function WC(){const e=document.createElement("span");return e.setAttribu...
method pause (line 389) | pause(){this.paused=!0}
method resume (line 389) | resume(){this.paused=!1}
function HB (line 389) | function HB(e,{select:t=!1}={}){const n=document.activeElement;for(const...
function qB (line 389) | function qB(e){const t=wT(e),n=JC(t,e),r=JC(t.reverse(),e);return[n,r]}
function wT (line 389) | function wT(e){const t=[],n=document.createTreeWalker(e,NodeFilter.SHOW_...
function JC (line 389) | function JC(e,t){for(const n of e)if(!KB(n,{upTo:t}))return n}
function KB (line 389) | function KB(e,{upTo:t}){if(getComputedStyle(e).visibility==="hidden")ret...
function WB (line 389) | function WB(e){return e instanceof HTMLInputElement&&"select"in e}
function fa (line 389) | function fa(e,{select:t=!1}={}){if(e&&e.focus){const n=document.activeEl...
function GB (line 389) | function GB(){let e=[];return{add(t){const n=e[0];t!==n&&n?.pause(),e=ZC...
function ZC (line 389) | function ZC(e,t){const n=[...e],r=n.indexOf(t);return r!==-1&&n.splice(r...
function JB (line 389) | function JB(e){return e.filter(t=>t.tagName!=="A")}
function Es (line 389) | function Es(e){const[t,n]=y.useState(QB());return Ln(()=>{n(r=>r??String...
function zy (line 389) | function zy(e,t,n){return zr(e,Hs(t,n))}
function Mo (line 389) | function Mo(e,t){return typeof e=="function"?e(t):e}
function _o (line 389) | function _o(e){return e.split("-")[0]}
function oc (line 389) | function oc(e){return e.split("-")[1]}
function Gb (line 389) | function Gb(e){return e==="x"?"y":"x"}
function Jb (line 389) | function Jb(e){return e==="y"?"height":"width"}
function xa (line 389) | function xa(e){return["top","bottom"].includes(_o(e))?"y":"x"}
function Qb (line 389) | function Qb(e){return Gb(xa(e))}
function t3 (line 389) | function t3(e,t,n){n===void 0&&(n=!1);const r=oc(e),s=Qb(e),o=Jb(s);let ...
function n3 (line 389) | function n3(e){const t=Fp(e);return[Uy(e),t,Uy(t)]}
function Uy (line 389) | function Uy(e){return e.replace(/start|end/g,t=>e3[t])}
function r3 (line 389) | function r3(e,t,n){const r=["left","right"],s=["right","left"],o=["top",...
function s3 (line 389) | function s3(e,t,n,r){const s=oc(e);let o=r3(_o(e),n==="start",r);return ...
function Fp (line 389) | function Fp(e){return e.replace(/left|right|bottom|top/g,t=>XB[t])}
function o3 (line 389) | function o3(e){return{top:0,right:0,bottom:0,left:0,...e}}
function ST (line 389) | function ST(e){return typeof e!="number"?o3(e):{top:e,right:e,bottom:e,l...
function Lp (line 389) | function Lp(e){const{x:t,y:n,width:r,height:s}=e;return{width:r,height:s...
function YC (line 389) | function YC(e,t,n){let{reference:r,floating:s}=e;const o=xa(t),l=Qb(t),u...
function Bu (line 389) | async function Bu(e,t){var n;t===void 0&&(t={});const{x:r,y:s,platform:o...
method fn (line 389) | async fn(t){const{x:n,y:r,placement:s,rects:o,platform:l,elements:u,midd...
method fn (line 389) | async fn(t){var n,r;const{placement:s,middlewareData:o,rects:l,initialPl...
function XC (line 389) | function XC(e,t){return{top:e.top-t.height,right:e.right-t.width,bottom:...
function e1 (line 389) | function e1(e){return YB.some(t=>e[t]>=0)}
method fn (line 389) | async fn(t){const{rects:n}=t,{strategy:r="referenceHidden",...s}=Mo(e,t)...
function u3 (line 389) | async function u3(e,t){const{placement:n,platform:r,elements:s}=e,o=awai...
method fn (line 389) | async fn(t){var n,r;const{x:s,y:o,placement:l,middlewareData:u}=t,d=awai...
method fn (line 389) | async fn(t){const{x:n,y:r,placement:s}=t,{mainAxis:o=!0,crossAxis:l=!1,l...
method fn (line 389) | fn(t){const{x:n,y:r,placement:s,rects:o,middlewareData:l}=t,{offset:u=0,...
method fn (line 389) | async fn(t){const{placement:n,rects:r,platform:s,elements:o}=t,{apply:l=...
function ac (line 389) | function ac(e){return CT(e)?(e.nodeName||"").toLowerCase():"#document"}
function Vr (line 389) | function Vr(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t....
function Io (line 389) | function Io(e){var t;return(t=(CT(e)?e.ownerDocument:e.document)||window...
function CT (line 389) | function CT(e){return e instanceof Node||e instanceof Vr(e).Node}
function Gs (line 389) | function Gs(e){return e instanceof Element||e instanceof Vr(e).Element}
function Js (line 389) | function Js(e){return e instanceof HTMLElement||e instanceof Vr(e).HTMLE...
function t1 (line 389) | function t1(e){return typeof ShadowRoot>"u"?!1:e instanceof ShadowRoot||...
function wd (line 389) | function wd(e){const{overflow:t,overflowX:n,overflowY:r,display:s}=Ns(e)...
function g3 (line 389) | function g3(e){return["table","td","th"].includes(ac(e))}
function Rh (line 389) | function Rh(e){return[":popover-open",":modal"].some(t=>{try{return e.ma...
function Zb (line 389) | function Zb(e){const t=Yb(),n=Ns(e);return n.transform!=="none"||n.persp...
function m3 (line 389) | function m3(e){let t=wa(e);for(;Js(t)&&!zl(t);){if(Rh(t))return null;if(...
function Yb (line 389) | function Yb(){return typeof CSS>"u"||!CSS.supports?!1:CSS.supports("-web...
function zl (line 389) | function zl(e){return["html","body","#document"].includes(ac(e))}
function Ns (line 389) | function Ns(e){return Vr(e).getComputedStyle(e)}
function Ph (line 389) | function Ph(e){return Gs(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollT...
function wa (line 389) | function wa(e){if(ac(e)==="html")return e;const t=e.assignedSlot||e.pare...
function ET (line 389) | function ET(e){const t=wa(e);return zl(t)?e.ownerDocument?e.ownerDocumen...
function zu (line 389) | function zu(e,t,n){var r;t===void 0&&(t=[]),n===void 0&&(n=!0);const s=E...
function kT (line 389) | function kT(e){const t=Ns(e);let n=parseFloat(t.width)||0,r=parseFloat(t...
function Xb (line 389) | function Xb(e){return Gs(e)?e:e.contextElement}
function Rl (line 389) | function Rl(e){const t=Xb(e);if(!Js(t))return ba(1);const n=t.getBoundin...
function jT (line 389) | function jT(e){const t=Vr(e);return!Yb()||!t.visualViewport?v3:{x:t.visu...
function y3 (line 389) | function y3(e,t,n){return t===void 0&&(t=!1),!n||t&&n!==Vr(e)?!1:t}
function Ci (line 389) | function Ci(e,t,n,r){t===void 0&&(t=!1),n===void 0&&(n=!1);const s=e.get...
function b3 (line 389) | function b3(e){let{elements:t,rect:n,offsetParent:r,strategy:s}=e;const ...
function x3 (line 389) | function x3(e){return Array.from(e.getClientRects())}
function TT (line 389) | function TT(e){return Ci(Io(e)).left+Ph(e).scrollLeft}
function w3 (line 389) | function w3(e){const t=Io(e),n=Ph(e),r=e.ownerDocument.body,s=zr(t.scrol...
function S3 (line 389) | function S3(e,t){const n=Vr(e),r=Io(e),s=n.visualViewport;let o=r.client...
function C3 (line 389) | function C3(e,t){const n=Ci(e,!0,t==="fixed"),r=n.top+e.clientTop,s=n.le...
function n1 (line 389) | function n1(e,t,n){let r;if(t==="viewport")r=S3(e,n);else if(t==="docume...
function NT (line 389) | function NT(e,t){const n=wa(e);return n===t||!Gs(n)||zl(n)?!1:Ns(n).posi...
function E3 (line 389) | function E3(e,t){const n=t.get(e);if(n)return n;let r=zu(e,[],!1).filter...
function k3 (line 389) | function k3(e){let{element:t,boundary:n,rootBoundary:r,strategy:s}=e;con...
function j3 (line 389) | function j3(e){const{width:t,height:n}=kT(e);return{width:t,height:n}}
function T3 (line 389) | function T3(e,t,n){const r=Js(t),s=Io(t),o=n==="fixed",l=Ci(e,!0,o,t);le...
function Cv (line 389) | function Cv(e){return Ns(e).position==="static"}
function r1 (line 389) | function r1(e,t){return!Js(e)||Ns(e).position==="fixed"?null:t?t(e):e.of...
function MT (line 389) | function MT(e,t){const n=Vr(e);if(Rh(e))return n;if(!Js(e)){let s=wa(e);...
function M3 (line 389) | function M3(e){return Ns(e).direction==="rtl"}
function R3 (line 389) | function R3(e,t){let n=null,r;const s=Io(e);function o(){var u;clearTime...
function _T (line 389) | function _T(e,t,n,r){r===void 0&&(r={});const{ancestorScroll:s=!0,ancest...
function $p (line 389) | function $p(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typ...
function RT (line 389) | function RT(e){return typeof window>"u"?1:(e.ownerDocument.defaultView||...
function o1 (line 389) | function o1(e,t){const n=RT(e);return Math.round(t*n)/n}
function a1 (line 389) | function a1(e){const t=y.useRef(e);return hp(()=>{t.current=e}),t}
function PT (line 389) | function PT(e){e===void 0&&(e={});const{placement:t="bottom",strategy:n=...
function t (line 389) | function t(n){return{}.hasOwnProperty.call(n,"current")}
method fn (line 389) | fn(n){const{element:r,padding:s}=typeof e=="function"?e(n):e;return r&&t...
function zT (line 389) | function zT(e){const[t,n]=y.useState(void 0);return Ln(()=>{if(e){n({wid...
function K3 (line 389) | function K3(e){return e!==null}
method fn (line 389) | fn(t){const{placement:n,rects:r,middlewareData:s}=t,l=s.arrow?.centerOff...
function QT (line 389) | function QT(e){const[t,n="center"]=e.split("-");return[t,n]}
function J3 (line 389) | function J3(e,t){return y.useReducer((n,r)=>t[n][r]??n,e)}
function Q3 (line 389) | function Q3(e){const[t,n]=y.useState(),r=y.useRef({}),s=y.useRef(e),o=y....
function Vf (line 389) | function Vf(e){return e?.animationName||"none"}
function Z3 (line 389) | function Z3(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get...
function oz (line 389) | function oz(e,t){return t!=="rtl"?e:e==="ArrowLeft"?"ArrowRight":e==="Ar...
function az (line 389) | function az(e,t,n){const r=oz(e.key,n);if(!(t==="vertical"&&["ArrowLeft"...
function oN (line 389) | function oN(e,t=!1){const n=document.activeElement;for(const r of e)if(r...
function iz (line 389) | function iz(e,t){return e.map((n,r)=>e[(t+r)%e.length])}
function cN (line 389) | function cN(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty...
function dz (line 389) | function dz(e,t,n){if(n||arguments.length===2)for(var r=0,s=t.length,o;r...
function jv (line 389) | function jv(e,t){return typeof e=="function"?e(t):e&&(e.current=t),e}
function hz (line 389) | function hz(e,t){var n=y.useState(function(){return{value:e,callback:t,f...
function mz (line 389) | function mz(e,t){var n=hz(null,function(r){return e.forEach(function(s){...
function vz (line 389) | function vz(e){return e}
function yz (line 389) | function yz(e,t){t===void 0&&(t=vz);var n=[],r=!1,s={read:function(){if(...
function bz (line 389) | function bz(e){e===void 0&&(e={});var t=yz(null);return t.options=zs({as...
function xz (line 389) | function xz(e,t){return e.useMedium(t),uN}
function Sz (line 389) | function Sz(){if(!document)return null;var e=document.createElement("sty...
function Cz (line 389) | function Cz(e,t){e.styleSheet?e.styleSheet.cssText=t:e.appendChild(docum...
function Ez (line 389) | function Ez(e){var t=document.head||document.getElementsByTagName("head"...
function Hz (line 429) | function Hz(e){var t=y.useRef([]),n=y.useRef([0,0]),r=y.useRef(),s=y.use...
function qz (line 429) | function qz(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.ho...
function LN (line 429) | function LN(e){return e?"open":"closed"}
function zp (line 429) | function zp(e){return e==="indeterminate"}
function cx (line 429) | function cx(e){return zp(e)?"indeterminate":e?"checked":"unchecked"}
function gU (line 429) | function gU(e){const t=document.activeElement;for(const n of e)if(n===t|...
function mU (line 429) | function mU(e,t){return e.map((n,r)=>e[(t+r)%e.length])}
function vU (line 429) | function vU(e,t,n){const s=t.length>1&&Array.from(t).every(f=>f===t[0])?...
function yU (line 429) | function yU(e,t){const{x:n,y:r}=e;let s=!1;for(let o=0,l=t.length-1;o<t....
function bU (line 429) | function bU(e,t){if(!t)return!1;const n={x:e.clientX,y:e.clientY};return...
function Vu (line 429) | function Vu(e){return t=>t.pointerType==="mouse"?e(t):void 0}
function iM (line 429) | function iM(){const{t:e,i18n:t}=Ve(),n=r=>{t.changeLanguage(r),localStor...
function lM (line 429) | function lM(){const{t:e}=Ve(),{setTheme:t}=tc();return i.jsxs(Kr,{childr...
function a5 (line 429) | function a5(e){const[t,n]=y.useState("idle");return Ln(()=>{if(!e){n("er...
function vx (line 429) | function vx(e){return e?"open":"closed"}
function zM (line 433) | function zM({instanceId:e}){const[t,n]=y.useState(!1),r=dn(),{theme:s}=t...
function wx (line 433) | function wx(e){return e?"open":"closed"}
function j5 (line 433) | function j5(){const{t:e}=Ve(),t=y.useMemo(()=>[{id:"dashboard",title:e("...
function Ky (line 433) | function Ky(e,[t,n]){return Math.min(n,Math.max(t,e))}
function T5 (line 433) | function T5(e,t){return y.useReducer((n,r)=>t[n][r]??n,e)}
function m (line 433) | function m(g,x){return D5(g,l.current,u,x)}
function D (line 433) | function D(z){if(k.current){const Q=z.clientX-k.current.left,pe=z.client...
function qp (line 433) | function qp(e){return e?parseInt(e,10):0}
function r_ (line 433) | function r_(e,t){const n=e/t;return isNaN(n)?0:n}
function zh (line 433) | function zh(e){const t=r_(e.viewport,e.content),n=e.scrollbar.paddingSta...
function D5 (line 433) | function D5(e,t,n,r="ltr"){const s=zh(n),o=s/2,l=t||o,u=s-l,d=n.scrollba...
function p1 (line 433) | function p1(e,t,n="ltr"){const r=zh(t),s=t.scrollbar.paddingStart+t.scro...
function s_ (line 433) | function s_(e,t){return n=>{if(e[0]===e[1]||t[0]===t[1])return t[0];cons...
function o_ (line 433) | function o_(e,t){return e>0&&e<t}
function Uh (line 433) | function Uh(e,t){const n=Rn(e),r=y.useRef(0);return y.useEffect(()=>()=>...
function Ul (line 433) | function Ul(e,t){const n=Rn(t);Ln(()=>{let r=0;if(e){const s=new ResizeO...
function un (line 433) | function un({children:e}){const{instanceId:t}=ls();return i.jsx(VM,{chil...
function B5 (line 433) | function B5({children:e}){return i.jsxs("div",{className:"flex h-full mi...
function vu (line 433) | function vu({className:e,variant:t,...n}){return i.jsx("div",{className:...
function l_ (line 433) | function l_({status:e}){const{t}=Ve();return e?e==="open"?i.jsx(vu,{chil...
function c_ (line 433) | function c_({token:e,className:t}){const[n,r]=y.useState(!1);return i.js...
function nt (line 433) | function nt(e,t){const n=Ob(),r=cF({mutationFn:e});return(s,o)=>r.mutate...
function Hh (line 433) | function Hh(){const e=nt(Q5,{invalidateKeys:[["instance","fetchInstance"...
function Er (line 433) | function Er(e){let t;const n=Array.isArray(e);if(e instanceof Date)t=new...
function Nx (line 433) | function Nx(e){const t=qe.useRef(e);t.current=e,qe.useEffect(()=>{const ...
function e6 (line 433) | function e6(e){const t=Kh(),{control:n=t.control,disabled:r,name:s,exact...
function t6 (line 433) | function t6(e){const t=Kh(),{control:n=t.control,name:r,defaultValue:s,d...
function n6 (line 433) | function n6(e){const t=Kh(),{name:n,disabled:r,control:s=t.control,shoul...
function b1 (line 433) | function b1(e,t,n="validate"){if(vp(e)||Array.isArray(e)&&e.every(vp)||U...
function o6 (line 433) | function o6(e,t){const n=t.slice(0,-1).length;let r=0;for(;r<n;)e=wn(e)?...
function a6 (line 433) | function a6(e){for(const t in e)if(e.hasOwnProperty(t)&&!wn(e[t]))return...
function Dn (line 433) | function Dn(e,t){const n=Array.isArray(t)?t:Tx(t)?[t]:h_(t),r=n.length==...
method observers (line 433) | get observers(){return e}
function ui (line 433) | function ui(e,t){if(Qp(e)||Qp(t))return e===t;if(Tl(e)&&Tl(t))return e.g...
function Zp (line 433) | function Zp(e,t={}){const n=Array.isArray(e);if($n(e)||n)for(const r in ...
function k_ (line 433) | function k_(e,t,n){const r=Array.isArray(e);if($n(e)||r)for(const s in e...
function Rv (line 433) | function Rv(e){const t=e.ref;if(!(e.refs?e.refs.every(n=>n.disabled):t.d...
function w1 (line 433) | function w1(e,t,n){const r=_e(e,n);if(r||Tx(n))return{error:r,name:n};co...
function p6 (line 433) | function p6(e={}){let t={...f6,...e},n={submitCount:0,isDirty:!1,isLoadi...
function on (line 433) | function on(e={}){const t=qe.useRef(),n=qe.useRef(),[r,s]=qe.useState({i...
function v6 (line 433) | function v6(e,t=0){return(Wn[e[t+0]]+Wn[e[t+1]]+Wn[e[t+2]]+Wn[e[t+3]]+"-...
function b6 (line 433) | function b6(){if(!Jf&&(Jf=typeof crypto<"u"&&crypto.getRandomValues&&cry...
function E1 (line 433) | function E1(e,t,n){if(C1.randomUUID&&!e)return C1.randomUUID();e=e||{};v...
function t (line 433) | function t(s){}
function n (line 433) | function n(s){throw new Error}
function r (line 433) | function r(s,o=" | "){return s.map(l=>typeof l=="string"?`'${l}'`:l).joi...
class Hr (line 433) | class Hr extends Error{constructor(t){super(),this.issues=[],this.addIss...
method constructor (line 433) | constructor(t){super(),this.issues=[],this.addIssue=r=>{this.issues=[....
method errors (line 433) | get errors(){return this.issues}
method format (line 433) | format(t){const n=t||function(o){return o.message},r={_errors:[]},s=o=...
method assert (line 433) | static assert(t){if(!(t instanceof Hr))throw new Error(`Not a ZodError...
method toString (line 433) | toString(){return this.message}
method message (line 433) | get message(){return JSON.stringify(this.issues,Ot.jsonStringifyReplac...
method isEmpty (line 433) | get isEmpty(){return this.issues.length===0}
method flatten (line 433) | flatten(t=n=>n.message){const n={},r=[];for(const s of this.issues)s.p...
method formErrors (line 433) | get formErrors(){return this.flatten()}
function S6 (line 433) | function S6(e){N_=e}
function Yp (line 433) | function Yp(){return N_}
function Ae (line 433) | function Ae(e,t){const n=Yp(),r=Xp({issueData:t,data:e.data,path:e.path,...
class sr (line 433) | class sr{constructor(){this.value="valid"}dirty(){this.value==="valid"&&...
method constructor (line 433) | constructor(){this.value="valid"}
method dirty (line 433) | dirty(){this.value==="valid"&&(this.value="dirty")}
method abort (line 433) | abort(){this.value!=="aborted"&&(this.value="aborted")}
method mergeArray (line 433) | static mergeArray(t,n){const r=[];for(const s of n){if(s.status==="abo...
method mergeObjectAsync (line 433) | static async mergeObjectAsync(t,n){const r=[];for(const s of n){const ...
method mergeObjectSync (line 433) | static mergeObjectSync(t,n){const r={};for(const s of n){const{key:o,v...
function eh (line 433) | function eh(e,t,n,r){if(typeof t=="function"?e!==t||!0:!t.has(e))throw n...
function M_ (line 433) | function M_(e,t,n,r,s){if(typeof t=="function"?e!==t||!0:!t.has(e))throw...
class Qs (line 433) | class Qs{constructor(t,n,r,s){this._cachedPath=[],this.parent=t,this.dat...
method constructor (line 433) | constructor(t,n,r,s){this._cachedPath=[],this.parent=t,this.data=n,thi...
method path (line 433) | get path(){return this._cachedPath.length||(this._key instanceof Array...
method error (line 433) | get error(){if(this._error)return this._error;const n=new Hr(e.common.is...
function yt (line 433) | function yt(e){if(!e)return{};const{errorMap:t,invalid_type_error:n,requ...
class St (line 433) | class St{constructor(t){this.spa=this.safeParseAsync,this._def=t,this.pa...
method constructor (line 433) | constructor(t){this.spa=this.safeParseAsync,this._def=t,this.parse=thi...
method description (line 433) | get description(){return this._def.description}
method _getType (line 433) | _getType(t){return pa(t.data)}
method _getOrReturnCtx (line 433) | _getOrReturnCtx(t,n){return n||{common:t.parent.common,data:t.data,par...
method _processInputParams (line 433) | _processInputParams(t){return{status:new sr,ctx:{common:t.parent.commo...
method _parseSync (line 433) | _parseSync(t){const n=this._parse(t);if(qu(n))throw new Error("Synchro...
method _parseAsync (line 433) | _parseAsync(t){const n=this._parse(t);return Promise.resolve(n)}
method parse (line 433) | parse(t,n){const r=this.safeParse(t,n);if(r.success)return r.data;thro...
method safeParse (line 433) | safeParse(t,n){var r;const s={common:{issues:[],async:(r=n?.async)!==n...
method parseAsync (line 433) | async parseAsync(t,n){const r=await this.safeParseAsync(t,n);if(r.succ...
method safeParseAsync (line 433) | async safeParseAsync(t,n){const r={common:{issues:[],contextualErrorMa...
method refine (line 433) | refine(t,n){const r=s=>typeof n=="string"||typeof n>"u"?{message:n}:ty...
method refinement (line 433) | refinement(t,n){return this._refinement((r,s)=>t(r)?!0:(s.addIssue(typ...
method _refinement (line 433) | _refinement(t){return new Ms({schema:this,typeName:it.ZodEffects,effec...
method superRefine (line 433) | superRefine(t){return this._refinement(t)}
method optional (line 433) | optional(){return Ws.create(this,this._def)}
method nullable (line 433) | nullable(){return ka.create(this,this._def)}
method nullish (line 433) | nullish(){return this.nullable().optional()}
method array (line 433) | array(){return ks.create(this,this._def)}
method promise (line 433) | promise(){return ql.create(this,this._def)}
method or (line 433) | or(t){return Ju.create([this,t],this._def)}
method and (line 433) | and(t){return Qu.create(this,t,this._def)}
method transform (line 433) | transform(t){return new Ms({...yt(this._def),schema:this,typeName:it.Z...
method default (line 433) | default(t){const n=typeof t=="function"?t:()=>t;return new td({...yt(t...
method brand (line 433) | brand(){return new Rx({typeName:it.ZodBranded,type:this,...yt(this._de...
method catch (line 433) | catch(t){const n=typeof t=="function"?t:()=>t;return new nd({...yt(thi...
method describe (line 433) | describe(t){const n=this.constructor;return new n({...this._def,descri...
method pipe (line 433) | pipe(t){return kd.create(this,t)}
method readonly (line 433) | readonly(){return rd.create(this)}
method isOptional (line 433) | isOptional(){return this.safeParse(void 0).success}
method isNullable (line 433) | isNullable(){return this.safeParse(null).success}
function R_ (line 433) | function R_(e){let t="([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d";return e.preci...
function D6 (line 433) | function D6(e){return new RegExp(`^${R_(e)}$`)}
function P_ (line 433) | function P_(e){let t=`${__}T${R_(e)}`;const n=[];return n.push(e.local?"...
function F6 (line 433) | function F6(e,t){return!!((t==="v4"||!t)&&P6.test(e)||(t==="v6"||!t)&&O6...
class Cs (line 433) | class Cs extends St{_parse(t){if(this._def.coerce&&(t.data=String(t.data...
method _parse (line 433) | _parse(t){if(this._def.coerce&&(t.data=String(t.data)),this._getType(t...
method _regex (line 433) | _regex(t,n,r){return this.refinement(s=>t.test(s),{validation:n,code:C...
method _addCheck (line 433) | _addCheck(t){return new Cs({...this._def,checks:[...this._def.checks,t...
method email (line 433) | email(t){return this._addCheck({kind:"email",...Ze.errToObj(t)})}
method url (line 433) | url(t){return this._addCheck({kind:"url",...Ze.errToObj(t)})}
method emoji (line 433) | emoji(t){return this._addCheck({kind:"emoji",...Ze.errToObj(t)})}
method uuid (line 433) | uuid(t){return this._addCheck({kind:"uuid",...Ze.errToObj(t)})}
method nanoid (line 433) | nanoid(t){return this._addCheck({kind:"nanoid",...Ze.errToObj(t)})}
method cuid (line 433) | cuid(t){return this._addCheck({kind:"cuid",...Ze.errToObj(t)})}
method cuid2 (line 433) | cuid2(t){return this._addCheck({kind:"cuid2",...Ze.errToObj(t)})}
method ulid (line 433) | ulid(t){return this._addCheck({kind:"ulid",...Ze.errToObj(t)})}
method base64 (line 433) | base64(t){return this._addCheck({kind:"base64",...Ze.errToObj(t)})}
method ip (line 433) | ip(t){return this._addCheck({kind:"ip",...Ze.errToObj(t)})}
method datetime (line 433) | datetime(t){var n,r;return typeof t=="string"?this._addCheck({kind:"da...
method date (line 433) | date(t){return this._addCheck({kind:"date",message:t})}
method time (line 433) | time(t){return typeof t=="string"?this._addCheck({kind:"time",precisio...
method duration (line 433) | duration(t){return this._addCheck({kind:"duration",...Ze.errToObj(t)})}
method regex (line 433) | regex(t,n){return this._addCheck({kind:"regex",regex:t,...Ze.errToObj(...
method includes (line 433) | includes(t,n){return this._addCheck({kind:"includes",value:t,position:...
method startsWith (line 433) | startsWith(t,n){return this._addCheck({kind:"startsWith",value:t,...Ze...
method endsWith (line 433) | endsWith(t,n){return this._addCheck({kind:"endsWith",value:t,...Ze.err...
method min (line 433) | min(t,n){return this._addCheck({kind:"min",value:t,...Ze.errToObj(n)})}
method max (line 433) | max(t,n){return this._addCheck({kind:"max",value:t,...Ze.errToObj(n)})}
method length (line 433) | length(t,n){return this._addCheck({kind:"length",value:t,...Ze.errToOb...
method nonempty (line 433) | nonempty(t){return this.min(1,Ze.errToObj(t))}
method trim (line 433) | trim(){return new Cs({...this._def,checks:[...this._def.checks,{kind:"...
method toLowerCase (line 433) | toLowerCase(){return new Cs({...this._def,checks:[...this._def.checks,...
method toUpperCase (line 433) | toUpperCase(){return new Cs({...this._def,checks:[...this._def.checks,...
method isDatetime (line 433) | get isDatetime(){return!!this._def.checks.find(t=>t.kind==="datetime")}
method isDate (line 433) | get isDate(){return!!this._def.checks.find(t=>t.kind==="date")}
method isTime (line 433) | get isTime(){return!!this._def.checks.find(t=>t.kind==="time")}
method isDuration (line 433) | get isDuration(){return!!this._def.checks.find(t=>t.kind==="duration")}
method isEmail (line 433) | get isEmail(){return!!this._def.checks.find(t=>t.kind==="email")}
method isURL (line 433) | get isURL(){return!!this._def.checks.find(t=>t.kind==="url")}
method isEmoji (line 433) | get isEmoji(){return!!this._def.checks.find(t=>t.kind==="emoji")}
method isUUID (line 433) | get isUUID(){return!!this._def.checks.find(t=>t.kind==="uuid")}
method isNANOID (line 433) | get isNANOID(){return!!this._def.checks.find(t=>t.kind==="nanoid")}
method isCUID (line 433) | get isCUID(){return!!this._def.checks.find(t=>t.kind==="cuid")}
method isCUID2 (line 433) | get isCUID2(){return!!this._def.checks.find(t=>t.kind==="cuid2")}
method isULID (line 433) | get isULID(){return!!this._def.checks.find(t=>t.kind==="ulid")}
method isIP (line 433) | get isIP(){return!!this._def.checks.find(t=>t.kind==="ip")}
method isBase64 (line 433) | get isBase64(){return!!this._def.checks.find(t=>t.kind==="base64")}
method minLength (line 433) | get minLength(){let t=null;for(const n of this._def.checks)n.kind==="m...
method maxLength (line 433) | get maxLength(){let t=null;for(const n of this._def.checks)n.kind==="m...
function L6 (line 433) | function L6(e,t){const n=(e.toString().split(".")[1]||"").length,r=(t.to...
class Sa (line 433) | class Sa extends St{constructor(){super(...arguments),this.min=this.gte,...
method constructor (line 433) | constructor(){super(...arguments),this.min=this.gte,this.max=this.lte,...
method _parse (line 433) | _parse(t){if(this._def.coerce&&(t.data=Number(t.data)),this._getType(t...
method gte (line 433) | gte(t,n){return this.setLimit("min",t,!0,Ze.toString(n))}
method gt (line 433) | gt(t,n){return this.setLimit("min",t,!1,Ze.toString(n))}
method lte (line 433) | lte(t,n){return this.setLimit("max",t,!0,Ze.toString(n))}
method lt (line 433) | lt(t,n){return this.setLimit("max",t,!1,Ze.toString(n))}
method setLimit (line 433) | setLimit(t,n,r,s){return new Sa({...this._def,checks:[...this._def.che...
method _addCheck (line 433) | _addCheck(t){return new Sa({...this._def,checks:[...this._def.checks,t...
method int (line 433) | int(t){return this._addCheck({kind:"int",message:Ze.toString(t)})}
method positive (line 433) | positive(t){return this._addCheck({kind:"min",value:0,inclusive:!1,mes...
method negative (line 433) | negative(t){return this._addCheck({kind:"max",value:0,inclusive:!1,mes...
method nonpositive (line 433) | nonpositive(t){return this._addCheck({kind:"max",value:0,inclusive:!0,...
method nonnegative (line 433) | nonnegative(t){return this._addCheck({kind:"min",value:0,inclusive:!0,...
method multipleOf (line 433) | multipleOf(t,n){return this._addCheck({kind:"multipleOf",value:t,messa...
method finite (line 433) | finite(t){return this._addCheck({kind:"finite",message:Ze.toString(t)})}
method safe (line 433) | safe(t){return this._addCheck({kind:"min",inclusive:!0,value:Number.MI...
method minValue (line 433) | get minValue(){let t=null;for(const n of this._def.checks)n.kind==="mi...
method maxValue (line 433) | get maxValue(){let t=null;for(const n of this._def.checks)n.kind==="ma...
method isInt (line 433) | get isInt(){return!!this._def.checks.find(t=>t.kind==="int"||t.kind===...
method isFinite (line 433) | get isFinite(){let t=null,n=null;for(const r of this._def.checks){if(r...
class Ca (line 433) | class Ca extends St{constructor(){super(...arguments),this.min=this.gte,...
method constructor (line 433) | constructor(){super(...arguments),this.min=this.gte,this.max=this.lte}
method _parse (line 433) | _parse(t){if(this._def.coerce&&(t.data=BigInt(t.data)),this._getType(t...
method gte (line 433) | gte(t,n){return this.setLimit("min",t,!0,Ze.toString(n))}
method gt (line 433) | gt(t,n){return this.setLimit("min",t,!1,Ze.toString(n))}
method lte (line 433) | lte(t,n){return this.setLimit("max",t,!0,Ze.toString(n))}
method lt (line 433) | lt(t,n){return this.setLimit("max",t,!1,Ze.toString(n))}
method setLimit (line 433) | setLimit(t,n,r,s){return new Ca({...this._def,checks:[...this._def.che...
method _addCheck (line 433) | _addCheck(t){return new Ca({...this._def,checks:[...this._def.checks,t...
method positive (line 433) | positive(t){return this._addCheck({kind:"min",value:BigInt(0),inclusiv...
method negative (line 433) | negative(t){return this._addCheck({kind:"max",value:BigInt(0),inclusiv...
method nonpositive (line 433) | nonpositive(t){return this._addCheck({kind:"max",value:BigInt(0),inclu...
method nonnegative (line 433) | nonnegative(t){return this._addCheck({kind:"min",value:BigInt(0),inclu...
method multipleOf (line 433) | multipleOf(t,n){return this._addCheck({kind:"multipleOf",value:t,messa...
method minValue (line 433) | get minValue(){let t=null;for(const n of this._def.checks)n.kind==="mi...
method maxValue (line 433) | get maxValue(){let t=null;for(const n of this._def.checks)n.kind==="ma...
class Ku (line 433) | class Ku extends St{_parse(t){if(this._def.coerce&&(t.data=!!t.data),thi...
method _parse (line 433) | _parse(t){if(this._def.coerce&&(t.data=!!t.data),this._getType(t)!==Le...
class Ti (line 433) | class Ti extends St{_parse(t){if(this._def.coerce&&(t.data=new Date(t.da...
method _parse (line 433) | _parse(t){if(this._def.coerce&&(t.data=new Date(t.data)),this._getType...
method _addCheck (line 433) | _addCheck(t){return new Ti({...this._def,checks:[...this._def.checks,t...
method min (line 433) | min(t,n){return this._addCheck({kind:"min",value:t.getTime(),message:Z...
method max (line 433) | max(t,n){return this._addCheck({kind:"max",value:t.getTime(),message:Z...
method minDate (line 433) | get minDate(){let t=null;for(const n of this._def.checks)n.kind==="min...
method maxDate (line 433) | get maxDate(){let t=null;for(const n of this._def.checks)n.kind==="max...
class th (line 433) | class th extends St{_parse(t){if(this._getType(t)!==Le.symbol){const r=t...
method _parse (line 433) | _parse(t){if(this._getType(t)!==Le.symbol){const r=this._getOrReturnCt...
class Wu (line 433) | class Wu extends St{_parse(t){if(this._getType(t)!==Le.undefined){const ...
method _parse (line 433) | _parse(t){if(this._getType(t)!==Le.undefined){const r=this._getOrRetur...
class Gu (line 433) | class Gu extends St{_parse(t){if(this._getType(t)!==Le.null){const r=thi...
method _parse (line 433) | _parse(t){if(this._getType(t)!==Le.null){const r=this._getOrReturnCtx(...
class Hl (line 433) | class Hl extends St{constructor(){super(...arguments),this._any=!0}_pars...
method constructor (line 433) | constructor(){super(...arguments),this._any=!0}
method _parse (line 433) | _parse(t){return fr(t.data)}
class mi (line 433) | class mi extends St{constructor(){super(...arguments),this._unknown=!0}_...
method constructor (line 433) | constructor(){super(...arguments),this._unknown=!0}
method _parse (line 433) | _parse(t){return fr(t.data)}
class Ro (line 433) | class Ro extends St{_parse(t){const n=this._getOrReturnCtx(t);return Ae(...
method _parse (line 433) | _parse(t){const n=this._getOrReturnCtx(t);return Ae(n,{code:Ce.invalid...
class nh (line 433) | class nh extends St{_parse(t){if(this._getType(t)!==Le.undefined){const ...
method _parse (line 433) | _parse(t){if(this._getType(t)!==Le.undefined){const r=this._getOrRetur...
class ks (line 433) | class ks extends St{_parse(t){const{ctx:n,status:r}=this._processInputPa...
method _parse (line 433) | _parse(t){const{ctx:n,status:r}=this._processInputParams(t),s=this._de...
method element (line 433) | get element(){return this._def.type}
method min (line 433) | min(t,n){return new ks({...this._def,minLength:{value:t,message:Ze.toS...
method max (line 433) | max(t,n){return new ks({...this._def,maxLength:{value:t,message:Ze.toS...
method length (line 433) | length(t,n){return new ks({...this._def,exactLength:{value:t,message:Z...
method nonempty (line 433) | nonempty(t){return this.min(1,t)}
function El (line 433) | function El(e){if(e instanceof gn){const t={};for(const n in e.shape){co...
class gn (line 433) | class gn extends St{constructor(){super(...arguments),this._cached=null,...
method constructor (line 433) | constructor(){super(...arguments),this._cached=null,this.nonstrict=thi...
method _getCached (line 433) | _getCached(){if(this._cached!==null)return this._cached;const t=this._...
method _parse (line 433) | _parse(t){if(this._getType(t)!==Le.object){const f=this._getOrReturnCt...
method shape (line 433) | get shape(){return this._def.shape()}
method strict (line 433) | strict(t){return Ze.errToObj,new gn({...this._def,unknownKeys:"strict"...
method strip (line 433) | strip(){return new gn({...this._def,unknownKeys:"strip"})}
method passthrough (line 433) | passthrough(){return new gn({...this._def,unknownKeys:"passthrough"})}
method extend (line 433) | extend(t){return new gn({...this._def,shape:()=>({...this._def.shape()...
method merge (line 433) | merge(t){return new gn({unknownKeys:t._def.unknownKeys,catchall:t._def...
method setKey (line 433) | setKey(t,n){return this.augment({[t]:n})}
method catchall (line 433) | catchall(t){return new gn({...this._def,catchall:t})}
method pick (line 433) | pick(t){const n={};return Ot.objectKeys(t).forEach(r=>{t[r]&&this.shap...
method omit (line 433) | omit(t){const n={};return Ot.objectKeys(this.shape).forEach(r=>{t[r]||...
method deepPartial (line 433) | deepPartial(){return El(this)}
method partial (line 433) | partial(t){const n={};return Ot.objectKeys(this.shape).forEach(r=>{con...
method required (line 433) | required(t){const n={};return Ot.objectKeys(this.shape).forEach(r=>{if...
method keyof (line 433) | keyof(){return O_(Ot.objectKeys(this.shape))}
class Ju (line 433) | class Ju extends St{_parse(t){const{ctx:n}=this._processInputParams(t),r...
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t),r=this._def.options...
method options (line 433) | get options(){return this._def.options}
class Wh (line 433) | class Wh extends St{_parse(t){const{ctx:n}=this._processInputParams(t);i...
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t);if(n.parsedType!==L...
method discriminator (line 433) | get discriminator(){return this._def.discriminator}
method options (line 433) | get options(){return this._def.options}
method optionsMap (line 433) | get optionsMap(){return this._def.optionsMap}
method create (line 433) | static create(t,n,r){const s=new Map;for(const o of n){const l=mo(o.sh...
function Zy (line 433) | function Zy(e,t){const n=pa(e),r=pa(t);if(e===t)return{valid:!0,data:e};...
class Qu (line 433) | class Qu extends St{_parse(t){const{status:n,ctx:r}=this._processInputPa...
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t),s=(o,l)=>{...
class Zs (line 433) | class Zs extends St{_parse(t){const{status:n,ctx:r}=this._processInputPa...
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t);if(r.parse...
method items (line 433) | get items(){return this._def.items}
method rest (line 433) | rest(t){return new Zs({...this._def,rest:t})}
class Zu (line 433) | class Zu extends St{get keySchema(){return this._def.keyType}get valueSc...
method keySchema (line 433) | get keySchema(){return this._def.keyType}
method valueSchema (line 433) | get valueSchema(){return this._def.valueType}
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t);if(r.parse...
method element (line 433) | get element(){return this._def.valueType}
method create (line 433) | static create(t,n,r){return n instanceof St?new Zu({keyType:t,valueTyp...
class rh (line 433) | class rh extends St{get keySchema(){return this._def.keyType}get valueSc...
method keySchema (line 433) | get keySchema(){return this._def.keyType}
method valueSchema (line 433) | get valueSchema(){return this._def.valueType}
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t);if(r.parse...
class Ni (line 433) | class Ni extends St{_parse(t){const{status:n,ctx:r}=this._processInputPa...
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t);if(r.parse...
method min (line 433) | min(t,n){return new Ni({...this._def,minSize:{value:t,message:Ze.toStr...
method max (line 433) | max(t,n){return new Ni({...this._def,maxSize:{value:t,message:Ze.toStr...
method size (line 433) | size(t,n){return this.min(t,n).max(t,n)}
method nonempty (line 433) | nonempty(t){return this.min(1,t)}
class Ol (line 433) | class Ol extends St{constructor(){super(...arguments),this.validate=this...
method constructor (line 433) | constructor(){super(...arguments),this.validate=this.implement}
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t);if(n.parsedType!==L...
method parameters (line 433) | parameters(){return this._def.args}
method returnType (line 433) | returnType(){return this._def.returns}
method args (line 433) | args(...t){return new Ol({...this._def,args:Zs.create(t).rest(mi.creat...
method returns (line 433) | returns(t){return new Ol({...this._def,returns:t})}
method implement (line 433) | implement(t){return this.parse(t)}
method strictImplement (line 433) | strictImplement(t){return this.parse(t)}
method create (line 433) | static create(t,n,r){return new Ol({args:t||Zs.create([]).rest(mi.crea...
class Yu (line 433) | class Yu extends St{get schema(){return this._def.getter()}_parse(t){con...
method schema (line 433) | get schema(){return this._def.getter()}
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t);return this._def.ge...
class Xu (line 433) | class Xu extends St{_parse(t){if(t.data!==this._def.value){const n=this....
method _parse (line 433) | _parse(t){if(t.data!==this._def.value){const n=this._getOrReturnCtx(t)...
method value (line 433) | get value(){return this._def.value}
function O_ (line 433) | function O_(e,t){return new Ea({values:e,typeName:it.ZodEnum,...yt(t)})}
class Ea (line 433) | class Ea extends St{constructor(){super(...arguments),yu.set(this,void 0...
method constructor (line 433) | constructor(){super(...arguments),yu.set(this,void 0)}
method _parse (line 433) | _parse(t){if(typeof t.data!="string"){const n=this._getOrReturnCtx(t),...
method options (line 433) | get options(){return this._def.values}
method enum (line 433) | get enum(){const t={};for(const n of this._def.values)t[n]=n;return t}
method Values (line 433) | get Values(){const t={};for(const n of this._def.values)t[n]=n;return t}
method Enum (line 433) | get Enum(){const t={};for(const n of this._def.values)t[n]=n;return t}
method extract (line 433) | extract(t,n=this._def){return Ea.create(t,{...this._def,...n})}
method exclude (line 433) | exclude(t,n=this._def){return Ea.create(this.options.filter(r=>!t.incl...
class ed (line 433) | class ed extends St{constructor(){super(...arguments),bu.set(this,void 0...
method constructor (line 433) | constructor(){super(...arguments),bu.set(this,void 0)}
method _parse (line 433) | _parse(t){const n=Ot.getValidEnumValues(this._def.values),r=this._getO...
method enum (line 433) | get enum(){return this._def.values}
class ql (line 433) | class ql extends St{unwrap(){return this._def.type}_parse(t){const{ctx:n...
method unwrap (line 433) | unwrap(){return this._def.type}
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t);if(n.parsedType!==L...
class Ms (line 433) | class Ms extends St{innerType(){return this._def.schema}sourceType(){ret...
method innerType (line 433) | innerType(){return this._def.schema}
method sourceType (line 433) | sourceType(){return this._def.schema._def.typeName===it.ZodEffects?thi...
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t),s=this._de...
class Ws (line 433) | class Ws extends St{_parse(t){return this._getType(t)===Le.undefined?fr(...
method _parse (line 433) | _parse(t){return this._getType(t)===Le.undefined?fr(void 0):this._def....
method unwrap (line 433) | unwrap(){return this._def.innerType}
class ka (line 433) | class ka extends St{_parse(t){return this._getType(t)===Le.null?fr(null)...
method _parse (line 433) | _parse(t){return this._getType(t)===Le.null?fr(null):this._def.innerTy...
method unwrap (line 433) | unwrap(){return this._def.innerType}
class td (line 433) | class td extends St{_parse(t){const{ctx:n}=this._processInputParams(t);l...
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t);let r=n.data;return...
method removeDefault (line 433) | removeDefault(){return this._def.innerType}
class nd (line 433) | class nd extends St{_parse(t){const{ctx:n}=this._processInputParams(t),r...
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t),r={...n,common:{......
method removeCatch (line 433) | removeCatch(){return this._def.innerType}
class sh (line 433) | class sh extends St{_parse(t){if(this._getType(t)!==Le.nan){const r=this...
method _parse (line 433) | _parse(t){if(this._getType(t)!==Le.nan){const r=this._getOrReturnCtx(t...
class Rx (line 433) | class Rx extends St{_parse(t){const{ctx:n}=this._processInputParams(t),r...
method _parse (line 433) | _parse(t){const{ctx:n}=this._processInputParams(t),r=n.data;return thi...
method unwrap (line 433) | unwrap(){return this._def.type}
class kd (line 433) | class kd extends St{_parse(t){const{status:n,ctx:r}=this._processInputPa...
method _parse (line 433) | _parse(t){const{status:n,ctx:r}=this._processInputParams(t);if(r.commo...
method create (line 433) | static create(t,n){return new kd({in:t,out:n,typeName:it.ZodPipeline})}
class rd (line 433) | class rd extends St{_parse(t){const n=this._def.innerType._parse(t),r=s=...
method _parse (line 433) | _parse(t){const n=this._def.innerType._parse(t),r=s=>(Hu(s)&&(s.value=...
method unwrap (line 433) | unwrap(){return this._def.innerType}
function I_ (line 433) | function I_(e,t={},n){return e?Hl.create().superRefine((r,s)=>{var o,l;i...
method util (line 433) | get util(){return Ot}
method objectUtil (line 433) | get objectUtil(){return Gy}
method ZodFirstPartyTypeKind (line 433) | get ZodFirstPartyTypeKind(){return it}
function gt (line 433) | function gt(e,t){for(var n=arguments.length,r=new Array(n>2?n-2:0),s=2;s...
function T1 (line 433) | function T1(e,t){return{type:Px,payload:{sourceClientOffset:t||null,clie...
function yp (line 433) | function yp(e){"@babel/helpers - typeof";return typeof Symbol=="function...
function C8 (line 433) | function C8(e,t,n){return t.split(".").reduce(function(r,s){return r&&r[...
function E8 (line 433) | function E8(e,t){return e.filter(function(n){return n!==t})}
function $_ (line 433) | function $_(e){return yp(e)==="object"}
function k8 (line 433) | function k8(e,t){var n=new Map,r=function(l){n.set(l,n.has(l)?n.get(l)+1...
function j8 (line 433) | function j8(e,t){return e.filter(function(n){return t.indexOf(n)>-1})}
function N8 (line 433) | function N8(e){return function(){var n=arguments.length>0&&arguments[0]!...
function M8 (line 433) | function M8(e,t,n){gt(!t.isDragging(),"Cannot call beginDrag while dragg...
function _8 (line 433) | function _8(e){gt(typeof e=="function","When clientOffset is provided, g...
function R8 (line 433) | function R8(e){gt($_(e),"Item must be an object.")}
function P8 (line 433) | function P8(e,t){for(var n=null,r=e.length-1;r>=0;r--)if(t.canDragSource...
function O8 (line 433) | function O8(e){return function(){var n=e.getMonitor();if(n.isDragging())...
function Yy (line 433) | function Yy(e,t){return t===null?e===null:Array.isArray(e)?e.some(functi...
function I8 (line 433) | function I8(e){return function(n){var r=arguments.length>1&&arguments[1]...
function A8 (line 433) | function A8(e){gt(Array.isArray(e),"Expected targetIds to be an array.")}
function D8 (line 433) | function D8(e,t,n){gt(t.isDragging(),"Cannot call hover while not draggi...
function F8 (line 433) | function F8(e,t,n){for(var r=e.length-1;r>=0;r--){var s=e[r],o=t.getTarg...
function L8 (line 433) | function L8(e,t,n){e.forEach(function(r){var s=n.getTarget(r);s.hover(t,...
function N1 (line 433) | function N1(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){v...
function M1 (line 433) | function M1(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=n...
function $8 (line 433) | function $8(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function B8 (line 433) | function B8(e){return function(){var n=arguments.length>0&&arguments[0]!...
function z8 (line 433) | function z8(e){gt(e.isDragging(),"Cannot call drop while not dragging.")...
function U8 (line 433) | function U8(e,t,n,r){var s=n.getTarget(e),o=s?s.drop(r,e):void 0;return ...
function V8 (line 433) | function V8(e){gt(typeof e>"u"||$_(e),"Drop result must either be an obj...
function H8 (line 433) | function H8(e){var t=e.getTargetIds().filter(e.canDropOnTarget,e);return...
function q8 (line 433) | function q8(e){return function(){var n=e.getMonitor(),r=e.getRegistry();...
function K8 (line 433) | function K8(e){gt(e.isDragging(),"Cannot call endDrag while not dragging...
function W8 (line 433) | function W8(e){return{beginDrag:N8(e),publishDragSource:O8(e),hover:I8(e...
function G8 (line 433) | function G8(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function J8 (line 433) | function J8(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function Q8 (line 433) | function Q8(e,t,n){return t&&J8(e.prototype,t),e}
function iu (line 433) | function iu(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 433) | function e(t,n){var r=this;G8(this,e),iu(this,"store",void 0),iu(this,"m...
function s (line 433) | function s(l){return function(){for(var u=arguments.length,d=new Array(u...
function ns (line 433) | function ns(e){return"Minified Redux error #"+e+"; visit https://redux.j...
function Y8 (line 433) | function Y8(e){if(typeof e!="object"||e===null)return!1;for(var t=e;Obje...
function B_ (line 433) | function B_(e,t,n){var r;if(typeof t=="function"&&typeof n=="function"||...
function eV (line 433) | function eV(e,t){return!e&&!t?!0:!e||!t?!1:e.x===t.x&&e.y===t.y}
function tV (line 433) | function tV(e,t){var n=arguments.length>2&&arguments[2]!==void 0?argumen...
function O1 (line 433) | function O1(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){v...
function I1 (line 433) | function I1(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=n...
function nV (line 433) | function nV(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function rV (line 433) | function rV(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[...
function sV (line 433) | function sV(e){return{type:Ix,payload:{sourceId:e}}}
function oV (line 433) | function oV(e){return{type:Ax,payload:{targetId:e}}}
function aV (line 433) | function aV(e){return{type:Dx,payload:{sourceId:e}}}
function iV (line 433) | function iV(e){return{type:Yh,payload:{targetId:e}}}
function D1 (line 433) | function D1(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){v...
function rs (line 433) | function rs(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=n...
function lV (line 433) | function lV(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function uV (line 433) | function uV(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[...
function dV (line 433) | function dV(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[...
function fV (line 433) | function fV(e,t){if(e===oh)return!1;if(e===Fx||typeof t>"u")return!0;var...
function pV (line 433) | function pV(){var e=arguments.length>1?arguments[1]:void 0;switch(e.type...
function hV (line 433) | function hV(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[...
function F1 (line 433) | function F1(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){v...
function L1 (line 433) | function L1(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=n...
function gV (line 433) | function gV(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function mV (line 433) | function mV(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[...
function vV (line 433) | function vV(e,t){return{x:e.x+t.x,y:e.y+t.y}}
function z_ (line 433) | function z_(e,t){return{x:e.x-t.x,y:e.y-t.y}}
function yV (line 433) | function yV(e){var t=e.clientOffset,n=e.initialClientOffset,r=e.initialS...
function bV (line 433) | function bV(e){var t=e.clientOffset,n=e.initialClientOffset;return!t||!n...
function xV (line 433) | function xV(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function wV (line 433) | function wV(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function SV (line 433) | function SV(e,t,n){return t&&wV(e.prototype,t),e}
function $1 (line 433) | function $1(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 433) | function e(t,n){xV(this,e),$1(this,"store",void 0),$1(this,"registry",vo...
function kV (line 433) | function kV(){return EV++}
function bp (line 433) | function bp(e){"@babel/helpers - typeof";return typeof Symbol=="function...
function jV (line 433) | function jV(e){gt(typeof e.canDrag=="function","Expected canDrag to be a...
function TV (line 433) | function TV(e){gt(typeof e.canDrop=="function","Expected canDrop to be a...
function Xy (line 433) | function Xy(e,t){if(t&&Array.isArray(e)){e.forEach(function(n){return Xy...
function V_ (line 433) | function V_(e){return function(){const n=setTimeout(s,0),r=setInterval(s...
function NV (line 433) | function NV(e){let t=1;const n=new U_(e),r=document.createTextNode("");r...
class _V (line 433) | class _V{enqueueTask(t){const{queue:n,requestFlush:r}=this;n.length||(r(...
method enqueueTask (line 433) | enqueueTask(t){const{queue:n,requestFlush:r}=this;n.length||(r(),this....
method constructor (line 433) | constructor(){this.queue=[],this.pendingErrors=[],this.flushing=!1,thi...
class RV (line 433) | class RV{call(){try{this.task&&this.task()}catch(t){this.onError(t)}fina...
method call (line 433) | call(){try{this.task&&this.task()}catch(t){this.onError(t)}finally{thi...
method constructor (line 433) | constructor(t,n){this.onError=t,this.release=n,this.task=null}
class PV (line 433) | class PV{create(t){const n=this.freeTasks,r=n.length?n.pop():new RV(this...
method create (line 433) | create(t){const n=this.freeTasks,r=n.length?n.pop():new RV(this.onErro...
method constructor (line 433) | constructor(t){this.onError=t,this.freeTasks=[]}
function IV (line 433) | function IV(e){H_.enqueueTask(OV.create(e))}
function AV (line 433) | function AV(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function DV (line 433) | function DV(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function FV (line 433) | function FV(e,t,n){return t&&DV(e.prototype,t),e}
function vl (line 433) | function vl(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function LV (line 433) | function LV(e,t){return UV(e)||zV(e,t)||BV(e,t)||$V()}
function $V (line 433) | function $V(){throw new TypeError(`Invalid attempt to destructure non-it...
function BV (line 434) | function BV(e,t){if(e){if(typeof e=="string")return z1(e,t);var n=Object...
function z1 (line 434) | function z1(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function zV (line 434) | function zV(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator...
function UV (line 434) | function UV(e){if(Array.isArray(e))return e}
function VV (line 434) | function VV(e){var t=kV().toString();switch(e){case os.SOURCE:return"S"....
function U1 (line 434) | function U1(e){switch(e[0]){case"S":return os.SOURCE;case"T":return os.T...
function V1 (line 434) | function V1(e,t){var n=e.entries(),r=!1;do{var s=n.next(),o=s.done,l=LV(...
function e (line 434) | function e(t){AV(this,e),vl(this,"types",new Map),vl(this,"dragSources",...
function qV (line 434) | function qV(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments...
function KV (line 434) | function KV(e){var t=typeof window<"u"&&window.__REDUX_DEVTOOLS_EXTENSIO...
function GV (line 434) | function GV(e,t){return YV(e)||ZV(e,t)||QV(e,t)||JV()}
function JV (line 434) | function JV(){throw new TypeError(`Invalid attempt to destructure non-it...
function QV (line 435) | function QV(e,t){if(e){if(typeof e=="string")return H1(e,t);var n=Object...
function H1 (line 435) | function H1(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function ZV (line 435) | function ZV(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator...
function YV (line 435) | function YV(e){if(Array.isArray(e))return e}
function XV (line 435) | function XV(e,t){if(e==null)return{};var n=eH(e,t),r,s;if(Object.getOwnP...
function eH (line 435) | function eH(e,t){if(e==null)return{};var n={},r=Object.keys(e),s,o;for(o...
function nH (line 435) | function nH(e){if("manager"in e){var t={dragDropManager:e.manager};retur...
function rH (line 435) | function rH(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments...
function q_ (line 435) | function q_(){return typeof global<"u"?global:window}
function sH (line 435) | function sH(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function oH (line 435) | function oH(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function aH (line 435) | function aH(e,t,n){return t&&oH(e.prototype,t),e}
function K1 (line 435) | function K1(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 435) | function e(t){sH(this,e),K1(this,"internalMonitor",void 0),K1(this,"sour...
function lH (line 435) | function lH(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function cH (line 435) | function cH(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function uH (line 435) | function uH(e,t,n){return t&&cH(e.prototype,t),e}
function W1 (line 435) | function W1(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 435) | function e(t){lH(this,e),W1(this,"internalMonitor",void 0),W1(this,"targ...
function fH (line 435) | function fH(e){if(typeof e.type!="string"){var t=e.type.displayName||e.t...
function pH (line 435) | function pH(e){return function(){var t=arguments.length>0&&arguments[0]!...
function K_ (line 435) | function K_(e){var t={};return Object.keys(e).forEach(function(n){var r=...
function G1 (line 435) | function G1(e,t){typeof e=="function"?e(t):e.current=t}
function hH (line 435) | function hH(e,t){var n=e.ref;return gt(typeof n!="string","Cannot connec...
function wp (line 435) | function wp(e){"@babel/helpers - typeof";return typeof Symbol=="function...
function eb (line 435) | function eb(e){return e!==null&&wp(e)==="object"&&Object.prototype.hasOw...
function tb (line 435) | function tb(e,t,n,r){var s=void 0;if(s!==void 0)return!!s;if(e===t)retur...
function gH (line 435) | function gH(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function mH (line 435) | function mH(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function vH (line 435) | function vH(e,t,n){return t&&mH(e.prototype,t),e}
function tr (line 435) | function tr(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 435) | function e(t){var n=this;gH(this,e),tr(this,"hooks",K_({dragSource:funct...
function bH (line 435) | function bH(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function xH (line 435) | function xH(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function wH (line 435) | function wH(e,t,n){return t&&xH(e.prototype,t),e}
function Bs (line 435) | function Bs(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 435) | function e(t){var n=this;bH(this,e),Bs(this,"hooks",K_({dropTarget:funct...
function CH (line 435) | function CH(e,t,n){var r=n.getRegistry(),s=r.addTarget(e,t);return[s,fun...
function EH (line 435) | function EH(e,t,n){var r=n.getRegistry(),s=r.addSource(e,t);return[s,fun...
function Sp (line 435) | function Sp(e){"@babel/helpers - typeof";return typeof Symbol=="function...
function kH (line 435) | function kH(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function jH (line 435) | function jH(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function TH (line 435) | function TH(e,t,n){return t&&jH(e.prototype,t),e}
function Fv (line 435) | function Fv(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 435) | function e(t,n,r){kH(this,e),Fv(this,"spec",void 0),Fv(this,"monitor",vo...
function MH (line 435) | function MH(e,t,n){var r=y.useMemo(function(){return new NH(e,t,n)},[t,n...
function ic (line 435) | function ic(){var e=y.useContext(L_),t=e.dragDropManager;return gt(t!=nu...
function _H (line 435) | function _H(e){return y.useMemo(function(){var t=e.type;return gt(t!=nul...
function RH (line 435) | function RH(e,t){return AH(e)||IH(e,t)||OH(e,t)||PH()}
function PH (line 435) | function PH(){throw new TypeError(`Invalid attempt to destructure non-it...
function OH (line 436) | function OH(e,t){if(e){if(typeof e=="string")return J1(e,t);var n=Object...
function J1 (line 436) | function J1(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function IH (line 436) | function IH(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator...
function AH (line 436) | function AH(e){if(Array.isArray(e))return e}
function DH (line 436) | function DH(e,t,n){var r=ic(),s=MH(e,t,n),o=_H(e);Mi(function(){if(o!=nu...
function FH (line 436) | function FH(e){return zH(e)||BH(e)||$H(e)||LH()}
function LH (line 436) | function LH(){throw new TypeError(`Invalid attempt to spread non-iterabl...
function $H (line 437) | function $H(e,t){if(e){if(typeof e=="string")return nb(e,t);var n=Object...
function BH (line 437) | function BH(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iter...
function zH (line 437) | function zH(e){if(Array.isArray(e))return nb(e)}
function nb (line 437) | function nb(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function W_ (line 437) | function W_(e,t){var n=FH(t||[]);return t==null&&typeof e!="function"&&n...
function UH (line 437) | function UH(){var e=ic();return y.useMemo(function(){return new iH(e)},[...
function VH (line 437) | function VH(e,t){var n=ic(),r=y.useMemo(function(){return new yH(n.getBa...
function HH (line 437) | function HH(){return Q1||(Q1=1,Lv=function e(t,n){if(t===n)return!0;if(t...
function WH (line 437) | function WH(e,t){return ZH(e)||QH(e,t)||JH(e,t)||GH()}
function GH (line 437) | function GH(){throw new TypeError(`Invalid attempt to destructure non-it...
function JH (line 438) | function JH(e,t){if(e){if(typeof e=="string")return Z1(e,t);var n=Object...
function Z1 (line 438) | function Z1(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function QH (line 438) | function QH(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator...
function ZH (line 438) | function ZH(e){if(Array.isArray(e))return e}
function YH (line 438) | function YH(e,t,n){var r=y.useState(function(){return t(e)}),s=WH(r,2),o...
function XH (line 438) | function XH(e,t){return rq(e)||nq(e,t)||tq(e,t)||eq()}
function eq (line 438) | function eq(){throw new TypeError(`Invalid attempt to destructure non-it...
function tq (line 439) | function tq(e,t){if(e){if(typeof e=="string")return Y1(e,t);var n=Object...
function Y1 (line 439) | function Y1(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function nq (line 439) | function nq(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator...
function rq (line 439) | function rq(e){if(Array.isArray(e))return e}
function sq (line 439) | function sq(e,t,n){var r=YH(e,t,n),s=XH(r,2),o=s[0],l=s[1];return Mi(fun...
function G_ (line 439) | function G_(e,t,n){return sq(t,e||function(){return{}},function(){return...
function oq (line 439) | function oq(e){return y.useMemo(function(){return e.hooks.dragSource()},...
function aq (line 439) | function aq(e){return y.useMemo(function(){return e.hooks.dragPreview()}...
function iq (line 439) | function iq(e,t){var n=W_(e,t);gt(!n.begin,"useDrag::spec.begin was depr...
function lq (line 439) | function lq(e){var t=e.accept;return y.useMemo(function(){return gt(e.ac...
function cq (line 439) | function cq(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function uq (line 439) | function uq(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function dq (line 439) | function dq(e,t,n){return t&&uq(e.prototype,t),e}
function X1 (line 439) | function X1(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 439) | function e(t,n){cq(this,e),X1(this,"spec",void 0),X1(this,"monitor",void...
function pq (line 439) | function pq(e,t){var n=y.useMemo(function(){return new fq(e,t)},[t]);ret...
function hq (line 439) | function hq(e,t){return yq(e)||vq(e,t)||mq(e,t)||gq()}
function gq (line 439) | function gq(){throw new TypeError(`Invalid attempt to destructure non-it...
function mq (line 440) | function mq(e,t){if(e){if(typeof e=="string")return eE(e,t);var n=Object...
function eE (line 440) | function eE(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,r=new A...
function vq (line 440) | function vq(e,t){var n=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator...
function yq (line 440) | function yq(e){if(Array.isArray(e))return e}
function bq (line 440) | function bq(e,t,n){var r=ic(),s=pq(e,t),o=lq(e);Mi(function(){var u=CH(o...
function xq (line 440) | function xq(){var e=ic();return y.useMemo(function(){return new dH(e)},[...
function wq (line 440) | function wq(e){var t=ic(),n=y.useMemo(function(){return new SH(t.getBack...
function Sq (line 440) | function Sq(e){return y.useMemo(function(){return e.hooks.dropTarget()},...
function Cq (line 440) | function Cq(e,t){var n=W_(e,t),r=xq(),s=wq(n.options);return bq(n,r,s),[...
function J_ (line 440) | function J_(e){var t=null,n=function(){return t==null&&(t=e()),t};return n}
function Eq (line 440) | function Eq(e,t){return e.filter(function(n){return n!==t})}
function kq (line 440) | function kq(e,t){var n=new Set,r=function(l){return n.add(l)};e.forEach(...
function jq (line 440) | function jq(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function Tq (line 440) | function Tq(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function Nq (line 440) | function Nq(e,t,n){return t&&Tq(e.prototype,t),e}
function tE (line 440) | function tE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 440) | function e(t){jq(this,e),tE(this,"entered",[]),tE(this,"isNodeInDocument...
function Rq (line 440) | function Rq(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function Pq (line 440) | function Pq(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function Oq (line 440) | function Oq(e,t,n){return t&&Pq(e.prototype,t),e}
function lu (line 440) | function lu(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 440) | function e(t,n){Rq(this,e),lu(this,"xs",void 0),lu(this,"ys",void 0),lu(...
function Z_ (line 440) | function Z_(e){var t=e.nodeType===Iq?e:e.parentElement;if(!t)return null...
function Qf (line 440) | function Qf(e){return{x:e.clientX,y:e.clientY}}
function Aq (line 440) | function Aq(e){var t;return e.nodeName==="IMG"&&(_q()||!((t=document.doc...
function Dq (line 440) | function Dq(e,t,n,r){var s=e?t.width:n,o=e?t.height:r;return Q_()&&e&&(o...
function Fq (line 440) | function Fq(e,t,n,r,s){var o=Aq(t),l=o?e:t,u=Z_(l),d={x:n.x-u.x,y:n.y-u....
function $v (line 440) | function $v(e,t,n){var r=t.reduce(function(s,o){return s||e.getData(o)},...
function Zf (line 440) | function Zf(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function Lq (line 441) | function Lq(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function $q (line 441) | function $q(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function Bq (line 441) | function Bq(e,t,n){return t&&$q(e.prototype,t),e}
function sE (line 441) | function sE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 441) | function e(t){Lq(this,e),sE(this,"item",void 0),sE(this,"config",void 0)...
function Uq (line 441) | function Uq(e,t){var n=new zq(rb[e]);return n.loadDataTransfer(t),n}
function Bv (line 441) | function Bv(e){if(!e)return null;var t=Array.prototype.slice.call(e.type...
function Vq (line 441) | function Vq(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function Hq (line 441) | function Hq(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function qq (line 441) | function qq(e,t,n){return t&&Hq(e.prototype,t),e}
function zv (line 441) | function zv(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 441) | function e(t,n){Vq(this,e),zv(this,"ownerDocument",null),zv(this,"global...
function oE (line 441) | function oE(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){v...
function aE (line 441) | function aE(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=n...
function Wq (line 441) | function Wq(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a...
function Gq (line 441) | function Gq(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.e...
function Jq (line 441) | function Jq(e,t,n){return t&&Gq(e.prototype,t),e}
function jt (line 441) | function jt(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enum...
function e (line 441) | function e(t,n,r){var s=this;Wq(this,e),jt(this,"options",void 0),jt(thi...
method "node_modules/classnames/index.js" (line 441) | "node_modules/classnames/index.js"(e,t){(function(){var n={}.hasOwnPrope...
function f7 (line 441) | function f7(e){var t=u7.call(e,uu),n=e[uu];try{e[uu]=void 0;var r=!0}cat...
function m7 (line 441) | function m7(e){return g7.call(e)}
function x7 (line 441) | function x7(e){return e==null?e===void 0?b7:y7:cE&&cE in Object(e)?p7(e)...
function w7 (line 441) | function w7(e){return e!=null&&typeof e=="object"}
function C7 (line 441) | function C7(e){return typeof e=="symbol"||Kl(e)&&lc(e)==S7}
function k7 (line 441) | function k7(e,t){for(var n=-1,r=e==null?0:e.length,s=Array(r);++n<r;)s[n...
function lR (line 441) | function lR(e){if(typeof e=="string")return e;if(sd(e))return j7(e,lR)+"...
function M7 (line 441) | function M7(e){var t=typeof e;return e!=null&&(t=="object"||t=="function")}
function I7 (line 441) | function I7(e){if(!cR(e))return!1;var t=lc(e);return t==R7||t==P7||t==_7...
function D7 (line 441) | function D7(e){return!!fE&&fE in e}
function B7 (line 441) | function B7(e){if(e!=null){try{return $7.call(e)}catch{}try{return e+""}...
function G7 (line 441) | function G7(e){if(!cR(e)||F7(e))return!1;var t=uR(e)?W7:U7;return t.test...
function Q7 (line 441) | function Q7(e,t){return e?.[t]}
function Y7 (line 441) | function Y7(e,t){var n=Z7(e,t);return J7(n)?n:void 0}
function eK (line 441) | function eK(){}
function nK (line 441) | function nK(e,t,n,r){for(var s=e.length,o=n+(r?1:-1);r?o--:++o<s;)if(t(e...
function sK (line 441) | function sK(e){return e!==e}
function aK (line 441) | function aK(e,t,n){for(var r=n-1,s=e.length;++r<s;)if(e[r]===t)return r;...
function lK (line 441) | function lK(e,t,n){return t===t?iK(e,t,n):rK(e,oK,n)}
function uK (line 441) | function uK(e,t){var n=e==null?0:e.length;return!!n&&cK(e,t,0)>-1}
function hK (line 441) | function hK(e,t){var n=typeof e;return t=t??fK,!!t&&(n=="number"||n!="sy...
function mK (line 441) | function mK(e,t){return e===t||e!==e&&t!==t}
function yK (line 441) | function yK(e){return typeof e=="number"&&e>-1&&e%1==0&&e<=vK}
function bK (line 441) | function bK(e){return e!=null&&fR(e.length)&&!uR(e)}
function SK (line 441) | function SK(e){var t=e&&e.constructor,n=typeof t=="function"&&t.prototyp...
function EK (line 441) | function EK(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}
function TK (line 441) | function TK(e){return Kl(e)&&lc(e)==jK}
function PK (line 441) | function PK(){return!1}
function iW (line 441) | function iW(e){return Kl(e)&&fR(e.length)&&!!rn[lc(e)]}
function cW (line 441) | function cW(e){return function(t){return e(t)}}
function mW (line 441) | function mW(e,t){var n=sd(e),r=!n&&RK(e),s=!n&&!r&&ob(e),o=!n&&!r&&!s&&m...
function yW (line 441) | function yW(e,t){return function(n){return e(t(n))}}
function EW (line 441) | function EW(e){if(!CK(e))return wW(e);var t=[];for(var n in Object(e))CW...
function jW (line 441) | function jW(e){return xK(e)?vW(e):kW(e)}
function MW (line 441) | function MW(){this.__data__=od?od(null):{},this.size=0}
function RW (line 441) | function RW(e){var t=this.has(e)&&delete this.__data__[e];return this.si...
function DW (line 441) | function DW(e){var t=this.__data__;if(od){var n=t[e];return n===OW?void ...
function BW (line 441) | function BW(e){var t=this.__data__;return od?t[e]!==void 0:$W.call(t,e)}
function VW (line 441) | function VW(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n...
function uc (line 441) | function uc(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){va...
function qW (line 441) | function qW(){this.__data__=[],this.size=0}
function WW (line 441) | function WW(e,t){for(var n=e.length;n--;)if(dR(e[n][0],t))return n;retur...
function QW (line 441) | function QW(e){var t=this.__data__,n=Xh(t,e);if(n<0)return!1;var r=t.len...
function YW (line 441) | function YW(e){var t=this.__data__,n=Xh(t,e);return n<0?void 0:t[n][1]}
function e9 (line 441) | function e9(e){return Xh(this.__data__,e)>-1}
function n9 (line 441) | function n9(e,t){var n=this.__data__,r=Xh(n,e);return r<0?(++this.size,n...
function dc (line 441) | function dc(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){va...
function o9 (line 441) | function o9(){this.size=0,this.__data__={hash:new yE,map:new(ad||eg),str...
function i9 (line 441) | function i9(e){var t=typeof e;return t=="string"||t=="number"||t=="symbo...
function c9 (line 441) | function c9(e,t){var n=e.__data__;return l9(t)?n[typeof t=="string"?"str...
function u9 (line 441) | function u9(e){var t=tg(this,e).delete(e);return this.size-=t?1:0,t}
function f9 (line 441) | function f9(e){return tg(this,e).get(e)}
function h9 (line 441) | function h9(e){return tg(this,e).has(e)}
function m9 (line 441) | function m9(e,t){var n=tg(this,e),r=n.size;return n.set(e,t),this.size+=...
function fc (line 441) | function fc(e){var t=-1,n=e==null?0:e.length;for(this.clear();++t<n;){va...
function y9 (line 441) | function y9(e){return e==null?"":N7(e)}
function b9 (line 441) | function b9(e,t){for(var n=-1,r=t.length,s=e.length;++n<r;)e[s+n]=t[n];r...
function w9 (line 441) | function w9(e){return function(t){return e?.[t]}}
function C9 (line 441) | function C9(){this.__data__=new eg,this.size=0}
function k9 (line 441) | function k9(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}
function T9 (line 441) | function T9(e){return this.__data__.get(e)}
function M9 (line 441) | function M9(e){return this.__data__.has(e)}
function P9 (line 441) | function P9(e,t){var n=this.__data__;if(n instanceof eg){var r=n.__data_...
function pc (line 441) | function pc(e){var t=this.__data__=new eg(e);this.size=t.size}
function I9 (line 441) | function I9(e,t){for(var n=-1,r=e==null?0:e.length,s=0,o=[];++n<r;){var ...
function D9 (line 441) | function D9(){return[]}
function U9 (line 441) | function U9(e,t,n){var r=t(e);return sd(e)?r:x9(r,n(e))}
function H9 (line 441) | function H9(e){return V9(e,TW,z9)}
function nG (line 441) | function nG(e){return this.__data__.set(e,tG),this}
function sG (line 441) | function sG(e){return this.__data__.has(e)}
function ah (line 441) | function ah(e){var t=-1,n=e==null?0:e.length;for(this.__data__=new vR;++...
function aG (line 441) | function aG(e,t){for(var n=-1,r=e==null?0:e.length;++n<r;)if(t(e[n],n,e)...
function lG (line 441) | function lG(e,t){return e.has(t)}
function dG (line 441) | function dG(e,t,n,r,s,o){var l=n&cG,u=e.length,d=t.length;if(u!=d&&!(l&&...
function fG (line 441) | function fG(e){var t=-1,n=Array(e.size);return e.forEach(function(r,s){n...
function hG (line 441) | function hG(e){var t=-1,n=Array(e.size);return e.forEach(function(r){n[+...
function NG (line 441) | function NG(e,t,n,r,s,o,l){switch(n){case TG:if(e.byteLength!=t.byteLeng...
function OG (line 441) | function OG(e,t,n,r,s,o){var l=n&_G,u=xE(e),d=u.length,f=xE(t),h=f.lengt...
function FG (line 441) | function FG(e,t,n,r,s,o){var l=sd(e),u=sd(t),d=l?_E:jE(e),f=u?_E:jE(t);d...
function SR (line 441) | function SR(e,t,n,r,s){return e===t?!0:e==null||t==null||!Kl(e)&&!Kl(t)?...
function BG (line 441) | function BG(e,t,n){for(var r=-1,s=e==null?0:e.length;++r<s;)if(n(t,e[r])...
function KG (line 441) | function KG(e){return e=yR(e),e&&qG.test(e)?e.replace(CR,HG):e}
function JG (line 441) | function JG(e){return e=yR(e),e&&GG.test(e)?e.replace(ER,"\\$&"):e}
function ZG (line 441) | function ZG(e,t){return $G(e,t)}
function rJ (line 441) | function rJ(e,t,n){var r=-1,s=dK,o=e.length,l=!0,u=[],d=u;if(n)l=!1,s=zG...
function oJ (line 441) | function oJ(e){return e&&e.length?sJ(e):[]}
function mJ (line 441) | function mJ(e){const t=e.map(r=>{const s=r-48*Math.floor(r/48);return St...
function vJ (line 441) | function vJ(e){switch(e){case Vs.ENTER:return[10,13];case Vs.TAB:return ...
function PE (line 441) | function PE(e){const{moveTag:t,readOnly:n,allowDragDrop:r}=e;return t!==...
function yJ (line 441) | function yJ(e){const{readOnly:t,allowDragDrop:n}=e;return!t&&n}
function NR (line 460) | function NR(e){const t=y.useRef({value:e,previous:e});return y.useMemo((...
function eP (line 460) | function eP(e){return e===""||e===void 0}
function nP (line 460) | function nP(e){const t=Rn(e),n=y.useRef(""),r=y.useRef(0),s=y.useCallbac...
function rP (line 460) | function rP(e,t,n){const s=t.length>1&&Array.from(t).every(f=>f===t[0])?...
function WJ (line 460) | function WJ(e,t){return e.map((n,r)=>e[(t+r)%e.length])}
function bP (line 460) | function bP(e){return e?"checked":"unchecked"}
function dQ (line 460) | function dQ({resetTable:e}){const{t}=Ve(),{createInstance:n}=Hh(),[r,s]=...
function bo (line 460) | function bo(e,t,{checkForDefaultPrevented:n=!0}={}){return function(s){i...
function IE (line 460) | function IE(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current...
function CP (line 460) | function CP(...e){return t=>{let n=!1;const r=e.map(s=>{const o=IE(s,t);...
function Ui (line 460) | function Ui(...e){return y.useCallback(CP(...e),e)}
function EP (line 460) | function EP(e,t=[]){let n=[];function r(o,l){const u=y.createContext(l),...
function fQ (line 460) | function fQ(...e){const t=e[0];if(e.length===1)return t;const n=()=>{con...
function pQ (line 460) | function pQ(e){const t=hQ(e),n=y.forwardRef((r,s)=>{const{children:o,......
function hQ (line 460) | function hQ(e){const t=y.forwardRef((n,r)=>{const{children:s,...o}=n;if(...
function gQ (line 460) | function gQ(e){const t=({children:n})=>i.jsx(i.Fragment,{children:n});re...
function mQ (line 460) | function mQ(e){return y.isValidElement(e)&&typeof e.type=="function"&&"_...
function vQ (line 460) | function vQ(e,t){const n={...t};for(const r in t){const s=e[r],o=t[r];/^...
function yQ (line 460) | function yQ(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get...
function xQ (line 460) | function xQ(e,t){e&&Ma.flushSync(()=>e.dispatchEvent(t))}
function ig (line 460) | function ig(e){const t=y.useRef(e);return y.useEffect(()=>{t.current=e})...
function wQ (line 460) | function wQ(e,t=globalThis?.document){const n=ig(e);y.useEffect(()=>{con...
function TQ (line 460) | function TQ(e,t=globalThis?.document){const n=ig(e),r=y.useRef(!1),s=y.u...
function NQ (line 460) | function NQ(e,t=globalThis?.document){const n=ig(e),r=y.useRef(!1);retur...
function DE (line 460) | function DE(){const e=new CustomEvent(hb);document.dispatchEvent(e)}
function NP (line 460) | function NP(e,t,n,{discrete:r}){const s=n.originalEvent.target,o=new Cus...
function RQ (line 460) | function RQ(e){const[t,n]=y.useState(MQ());return Ta(()=>{n(r=>r??String...
function IQ (line 460) | function IQ(e){const[t,n]=y.useState(void 0);return Ta(()=>{if(e){n({wid...
function $Q (line 460) | function $Q(e){return e!==null}
method fn (line 460) | fn(t){const{placement:n,rects:r,middlewareData:s}=t,l=s.arrow?.centerOff...
function $P (line 460) | function $P(e){const[t,n="center"]=e.split("-");return[t,n]}
function KQ (line 460) | function KQ(e,t){return y.useReducer((n,r)=>t[n][r]??n,e)}
function WQ (line 460) | function WQ(e){const[t,n]=y.useState(),r=y.useRef(null),s=y.useRef(e),o=...
function Xf (line 460) | function Xf(e){return e?.animationName||"none"}
function GQ (line 460) | function GQ(e){let t=Object.getOwnPropertyDescriptor(e.props,"ref")?.get...
function QQ (line 460) | function QQ({prop:e,defaultProp:t,onChange:n=()=>{},caller:r}){const[s,o...
function ZQ (line 460) | function ZQ({defaultProp:e,onChange:t}){const[n,r]=y.useState(e),s=y.use...
function YQ (line 460) | function YQ(e){return typeof e=="function"}
function dZ (line 460) | function dZ(e,t){const n=Math.abs(t.top-e.y),r=Math.abs(t.bottom-e.y),s=...
function fZ (line 460) | function fZ(e,t,n=5){const r=[];switch(t){case"top":r.push({x:e.x-n,y:e....
function pZ (line 460) | function pZ(e){const{top:t,right:n,bottom:r,left:s}=e;return[{x:s,y:t},{...
function hZ (line 460) | function hZ(e,t){const{x:n,y:r}=e;let s=!1;for(let o=0,l=t.length-1;o<t....
function gZ (line 460) | function gZ(e){const t=e.slice();return t.sort((n,r)=>n.x<r.x?-1:n.x>r.x...
function mZ (line 460) | function mZ(e){if(e.length<=1)return e.slice();const t=[];for(let r=0;r<...
function FE (line 460) | function FE({content:e,children:t,side:n="top"}){return i.jsx(vZ,{delayD...
function CZ (line 464) | function CZ(){const{t:e}=Ve(),[t,n]=y.useState(null),{deleteInstance:r,l...
function Kx (line 464) | function Kx(e=null){const t=NZ(),n=kr(e||t||null);return n.current===nul...
function eO (line 464) | function eO({children:e,className:t="",collapsedSize:n,collapsible:r,def...
function _Z (line 464) | function _Z(e,t){if(t){const n=(t&aO)!==0,r=(t&iO)!==0,s=(t&lO)!==0,o=(t...
function RZ (line 464) | function RZ(){di!==null&&(document.head.removeChild(di),vb=null,di=null)}
function Wv (line 464) | function Wv(e,t){const n=_Z(e,t);vb!==n&&(vb=n,di===null&&(di=document.c...
function nO (line 464) | function nO(e){return e.type==="keydown"}
function rO (line 464) | function rO(e){return e.type.startsWith("pointer")}
function sO (line 464) | function sO(e){return e.type.startsWith("mouse")}
function dg (line 464) | function dg(e){if(rO(e)){if(e.isPrimary)return{x:e.clientX,y:e.clientY}}...
function PZ (line 464) | function PZ(){if(typeof matchMedia=="function")return matchMedia("(point...
function OZ (line 464) | function OZ(e,t,n){return e.x<t.x+t.width&&e.x+e.width>t.x&&e.y<t.y+t.he...
function IZ (line 464) | function IZ(e,t){if(e===t)throw new Error("Cannot compare node with itse...
function DZ (line 464) | function DZ(e){var t;const n=getComputedStyle((t=oO(e))!==null&&t!==void...
function FZ (line 464) | function FZ(e){const t=getComputedStyle(e);return!!(t.position==="fixed"...
function $E (line 464) | function $E(e){let t=e.length;for(;t--;){const n=e[t];if(kt(n,"Missing n...
function BE (line 464) | function BE(e){return e&&Number(getComputedStyle(e).zIndex)||0}
function zE (line 464) | function zE(e){const t=[];for(;e;)t.push(e),e=oO(e);return t}
function oO (line 464) | function oO(e){const{parentNode:t}=e;return t&&t instanceof ShadowRoot?t...
function $Z (line 464) | function $Z(e,t,n,r,s){var o;const{ownerDocument:l}=t,u={direction:n,ele...
function UE (line 464) | function UE(e){const{target:t}=e,{x:n,y:r}=dg(e);ld=!0,Wx({target:t,x:n,...
function du (line 464) | function du(e){const{x:t,y:n}=dg(e);if(e.buttons===0&&(ld=!1,ch("up",e))...
function bl (line 464) | function bl(e){const{target:t}=e,{x:n,y:r}=dg(e);fg.clear(),ld=!1,js.len...
function Wx (line 464) | function Wx({target:e,x:t,y:n}){js.splice(0);let r=null;e instanceof HTM...
function Gv (line 464) | function Gv(e,t){fg.set(e,t)}
function Gx (line 464) | function Gx(){let e=!1,t=!1;js.forEach(r=>{const{direction:s}=r;s==="hor...
function lh (line 464) | function lh(){ha.forEach((e,t)=>{const{body:n}=t;n.removeEventListener("...
function ch (line 464) | function ch(e,t){cd.forEach(n=>{const{setResizeHandlerState:r}=n,s=js.in...
function kt (line 464) | function kt(e,t){if(!e)throw console.error(t),Error(t)}
function Ri (line 464) | function Ri(e,t,n=Jx){return e.toFixed(n)===t.toFixed(n)?0:e>t?1:-1}
function xo (line 464) | function xo(e,t,n=Jx){return Ri(e,t,n)===0}
function $r (line 464) | function $r(e,t,n){return Ri(e,t,n)===0}
function BZ (line 464) | function BZ(e,t,n){if(e.length!==t.length)return!1;for(let r=0;r<e.lengt...
function Ml (line 464) | function Ml({panelConstraints:e,panelIndex:t,size:n}){const r=e[t];kt(r!...
function wu (line 464) | function wu({delta:e,initialLayout:t,panelConstraints:n,pivotIndices:r,p...
function zZ (line 464) | function zZ({layout:e,panelsArray:t,pivotIndices:n}){let r=0,s=100,o=0,l...
function ud (line 464) | function ud(e,t=document){return Array.from(t.querySelectorAll(`[data-pa...
function uO (line 464) | function uO(e,t,n=document){const s=ud(e,n).findIndex(o=>o.getAttribute(...
function dO (line 464) | function dO(e,t,n){const r=uO(e,t,n);return r!=null?[r,r+1]:[-1,-1]}
function fO (line 464) | function fO(e,t=document){var n;if(t instanceof HTMLElement&&(t==null||(...
function pg (line 464) | function pg(e,t=document){const n=t.querySelector(`[data-panel-resize-ha...
function UZ (line 464) | function UZ(e,t,n,r=document){var s,o,l,u;const d=pg(t,r),f=ud(e,r),h=d?...
function VZ (line 464) | function VZ({committedValuesRef:e,eagerValuesRef:t,groupId:n,layout:r,pa...
function VE (line 464) | function VE(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;...
function pO (line 464) | function pO(e,t){const n=e==="horizontal",{x:r,y:s}=dg(t);return n?r:s}
function HZ (line 464) | function HZ(e,t,n,r,s){const o=n==="horizontal",l=pg(t,s);kt(l,`No resiz...
function qZ (line 464) | function qZ(e,t,n,r,s,o){if(nO(e)){const l=n==="horizontal";let u=0;e.sh...
function KZ (line 464) | function KZ({panelDataArray:e}){const t=Array(e.length),n=e.map(o=>o.con...
function xl (line 464) | function xl(e,t,n){t.forEach((r,s)=>{const o=e[s];kt(o,`Panel data not f...
function ep (line 464) | function ep(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;...
function WZ (line 464) | function WZ({defaultSize:e,dragState:t,layout:n,panelData:r,panelIndex:s...
function GZ (line 464) | function GZ(e,t=10){let n=null;return(...s)=>{n!==null&&clearTimeout(n),...
function HE (line 464) | function HE(e){try{if(typeof localStorage<"u")e.getItem=t=>localStorage....
function hO (line 464) | function hO(e){return`react-resizable-panels:${e}`}
function gO (line 464) | function gO(e){return e.map(t=>{const{constraints:n,id:r,idIsFromProps:s...
function mO (line 464) | function mO(e,t){try{const n=hO(e),r=t.getItem(n);if(r){const s=JSON.par...
function JZ (line 464) | function JZ(e,t,n){var r,s;const o=(r=mO(e,n))!==null&&r!==void 0?r:{},l...
function QZ (line 464) | function QZ(e,t,n,r,s){var o;const l=hO(e),u=gO(t),d=(o=mO(e,s))!==null&...
function qE (line 464) | function qE({layout:e,panelConstraints:t}){const n=[...e],r=n.reduce((o,...
function vO (line 464) | function vO({autoSaveId:e=null,children:t,className:n="",direction:r,for...
function kl (line 464) | function kl(e,t){return e.findIndex(n=>n===t||n.id===t.id)}
function ri (line 464) | function ri(e,t,n){const r=kl(e,t),o=r===e.length-1?[r-1,r]:[r,r+1],l=n[...
function YZ (line 464) | function YZ({disabled:e,handleId:t,resizeHandler:n,panelGroupElement:r})...
function bO (line 464) | function bO({children:e=null,className:t="",disabled:n=!1,hitAreaMargins...
function NO (line 464) | function NO(e,t){return`${e}-trigger-${t}`}
function MO (line 464) | function MO(e,t){return`${e}-content-${t}`}
function zo (line 464) | function zo(e){const t=o=>typeof window<"u"?window.matchMedia(o).matches...
function GE (line 464) | function GE(e){return e instanceof Uint8Array?e:e instanceof ArrayBuffer...
function oY (line 464) | function oY(e,t){if(OO&&e.data instanceof Blob)return e.data.arrayBuffer...
function dY (line 464) | function dY(){return new TransformStream({transform(e,t){oY(e,n=>{const ...
function tp (line 464) | function tp(e){return e.reduce((t,n)=>t+n.length,0)}
function np (line 464) | function np(e,t){if(e[0].length===t)return e.shift();const n=new Uint8Ar...
function fY (line 464) | function fY(e,t){Qv||(Qv=new TextDecoder);const n=[];let r=0,s=-1,o=!1;r...
function Pn (line 464) | function Pn(e){if(e)return pY(e)}
function pY (line 464) | function pY(e){for(var t in Pn.prototype)e[t]=Pn.prototype[t];return e}
function n (line 464) | function n(){this.off(e,n),t.apply(this,arguments)}
function $O (line 464) | function $O(e,...t){return t.reduce((n,r)=>(e.hasOwnProperty(r)&&(n[r]=e...
function mg (line 464) | function mg(e,t){t.useNativeTimers?(e.setTimeoutFn=gY.bind(as),e.clearTi...
function yY (line 464) | function yY(e){return typeof e=="string"?bY(e):Math.ceil((e.byteLength||...
function bY (line 464) | function bY(e){let t=0,n=0;for(let r=0,s=e.length;r<s;r++)t=e.charCodeAt...
function BO (line 464) | function BO(){return Date.now().toString(36).substring(3)+Math.random()....
function xY (line 464) | function xY(e){let t="";for(let n in e)e.hasOwnProperty(n)&&(t.length&&(...
function wY (line 464) | function wY(e){let t={},n=e.split("&");for(let r=0,s=n.length;r<s;r++){l...
class SY (line 464) | class SY extends Error{constructor(t,n,r){super(t),this.description=n,th...
method constructor (line 464) | constructor(t,n,r){super(t),this.description=n,this.context=r,this.typ...
class tw (line 464) | class tw extends Pn{constructor(t){super(),this.writable=!1,mg(this,t),t...
method constructor (line 464) | constructor(t){super(),this.writable=!1,mg(this,t),this.opts=t,this.qu...
method onError (line 464) | onError(t,n,r){return super.emitReserved("error",new SY(t,n,r)),this}
method open (line 464) | open(){return this.readyState="opening",this.doOpen(),this}
method close (line 464) | close(){return(this.readyState==="opening"||this.readyState==="open")&...
method send (line 464) | send(t){this.readyState==="open"&&this.write(t)}
method onOpen (line 464) | onOpen(){this.readyState="open",this.writable=!0,super.emitReserved("o...
method onData (line 464) | onData(t){const n=ew(t,this.socket.binaryType);this.onPacket(n)}
method onPacket (line 464) | onPacket(t){super.emitReserved("packet",t)}
method onClose (line 464) | onClose(t){this.readyState="closed",super.emitReserved("close",t)}
method pause (line 464) | pause(t){}
method createUri (line 464) | createUri(t,n={}){return t+"://"+this._hostname()+this._port()+this.op...
method _hostname (line 464) | _hostname(){const t=this.opts.hostname;return t.indexOf(":")===-1?t:"[...
method _port (line 464) | _port(){return this.opts.port&&(this.opts.secure&&+(this.opts.port!==4...
method _query (line 464) | _query(t){const n=xY(t);return n.length?"?"+n:""}
class CY (line 464) | class CY extends tw{constructor(){super(...arguments),this._polling=!1}g...
method constructor (line 464) | constructor(){super(...arguments),this._polling=!1}
method name (line 464) | get name(){return"polling"}
method doOpen (line 464) | doOpen(){this._poll()}
method pause (line 464) | pause(t){this.readyState="pausing";const n=()=>{this.readyState="pause...
method _poll (line 464) | _poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}
method onData (line 464) | onData(t){const n=r=>{if(this.readyState==="opening"&&r.type==="open"&...
method doClose (line 464) | doClose(){const t=()=>{this.write([{type:"close"}])};this.readyState==...
method write (line 464) | write(t){this.writable=!1,cY(t,n=>{this.doWrite(n,()=>{this.writable=!...
method uri (line 464) | uri(){const t=this.opts.secure?"https":"http",n=this.query||{};return ...
function kY (line 464) | function kY(){}
class jY (line 464) | class jY extends CY{constructor(t){if(super(t),typeof location<"u"){cons...
method constructor (line 464) | constructor(t){if(super(t),typeof location<"u"){const n=location.proto...
method doWrite (line 464) | doWrite(t,n){const r=this.request({method:"POST",data:t});r.on("succes...
method doPoll (line 464) | doPoll(){const t=this.request();t.on("data",this.onData.bind(this)),t....
method constructor (line 464) | constructor(t,n,r){super(),this.createRequest=t,mg(this,r),this._opts=r,...
method _create (line 464) | _create(){var t;const n=$O(this._opts,"agent","pfx","key","passphrase","...
method _onError (line 464) | _onError(t){this.emitReserved("error",t,this._xhr),this._cleanup(!0)}
method _cleanup (line 464) | _cleanup(t){if(!(typeof this._xhr>"u"||this._xhr===null)){if(this._xhr.o...
method _onLoad (line 464) | _onLoad(){const t=this._xhr.responseText;t!==null&&(this.emitReserved("d...
method abort (line 464) | abort(){this._cleanup()}
function QE (line 464) | function QE(){for(let e in Dl.requests)Dl.requests.hasOwnProperty(e)&&Dl...
class NY (line 464) | class NY extends jY{constructor(t){super(t);const n=t&&t.forceBase64;thi...
method constructor (line 464) | constructor(t){super(t);const n=t&&t.forceBase64;this.supportsBinary=T...
method request (line 464) | request(t={}){return Object.assign(t,{xd:this.xd},this.opts),new Dl(UO...
function UO (line 464) | function UO(e){const t=e.xdomain;try{if(typeof XMLHttpRequest<"u"&&(!t||...
class MY (line 464) | class MY extends tw{get name(){return"websocket"}doOpen(){const t=this.u...
method name (line 464) | get name(){return"websocket"}
method doOpen (line 464) | doOpen(){const t=this.uri(),n=this.opts.protocols,r=VO?{}:$O(this.opts...
method addEventListeners (line 464) | addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._...
method write (line 464) | write(t){this.writable=!1;for(let n=0;n<t.length;n++){const r=t[n],s=n...
method doClose (line 464) | doClose(){typeof this.ws<"u"&&(this.ws.onerror=()=>{},this.ws.close(),...
method uri (line 464) | uri(){const t=this.opts.secure?"wss":"ws",n=this.query||{};return this...
class _Y (line 464) | class _Y extends MY{createSocket(t,n,r){return VO?new Zv(t,n,r):n?new Zv...
method createSocket (line 464) | createSocket(t,n,r){return VO?new Zv(t,n,r):n?new Zv(t,n):new Zv(t)}
method doWrite (line 464) | doWrite(t,n){this.ws.send(n)}
class RY (line 464) | class RY extends tw{get name(){return"webtransport"}doOpen(){try{this._t...
method name (line 464) | get name(){return"webtransport"}
method doOpen (line 464) | doOpen(){try{this._transport=new WebTransport(this.createUri("https"),...
method write (line 464) | write(t){this.writable=!1;for(let n=0;n<t.length;n++){const r=t[n],s=n...
method doClose (line 464) | doClose(){var t;(t=this._transport)===null||t===void 0||t.close()}
function bb (line 464) | function bb(e){if(e.length>8e3)throw"URI too long";const t=e,n=e.indexOf...
function AY (line 464) | function AY(e,t){const n=/\/{2,9}/g,r=t.replace(n,"/").split("/");return...
function DY (line 464) | function DY(e,t){const n={};return t.replace(/(?:^|&)([^&=]*)=?([^&]*)/g...
class va (line 464) | class va extends Pn{constructor(t,n){if(super(),this.binaryType=hY,this....
method constructor (line 464) | constructor(t,n){if(super(),this.binaryType=hY,this.writeBuffer=[],thi...
method createTransport (line 464) | createTransport(t){const n=Object.assign({},this.opts.query);n.EIO=LO,...
method _open (line 464) | _open(){if(this.transports.length===0){this.setTimeoutFn(()=>{this.emi...
method setTransport (line 464) | setTransport(t){this.transport&&this.transport.removeAllListeners(),th...
method onOpen (line 464) | onOpen(){this.readyState="open",va.priorWebsocketSuccess=this.transpor...
method _onPacket (line 464) | _onPacket(t){if(this.readyState==="opening"||this.readyState==="open"|...
method onHandshake (line 464) | onHandshake(t){this.emitReserved("handshake",t),this.id=t.sid,this.tra...
method _resetPingTimeout (line 464) | _resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const ...
method _onDrain (line 464) | _onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBu...
method flush (line 464) | flush(){if(this.readyState!=="closed"&&this.transport.writable&&!this....
method _getWritablePackets (line 464) | _getWritablePackets(){if(!(this._maxPayload&&this.transport.name==="po...
method _hasPingExpired (line 464) | _hasPingExpired(){if(!this._pingTimeoutTime)return!0;const t=Date.now(...
method write (line 464) | write(t,n,r){return this._sendPacket("message",t,n,r),this}
method send (line 464) | send(t,n,r){return this._sendPacket("message",t,n,r),this}
method _sendPacket (line 464) | _sendPacket(t,n,r,s){if(typeof n=="function"&&(s=n,n=void 0),typeof r=...
method close (line 464) | close(){const t=()=>{this._onClose("forced close"),this.transport.clos...
method _onError (line 464) | _onError(t){if(va.priorWebsocketSuccess=!1,this.opts.tryAllTransports&...
method _onClose (line 464) | _onClose(t,n){if(this.readyState==="opening"||this.readyState==="open"...
class FY (line 464) | class FY extends va{constructor(){super(...arguments),this._upgrades=[]}...
method constructor (line 464) | constructor(){super(...arguments),this._upgrades=[]}
method onOpen (line 464) | onOpen(){if(super.onOpen(),this.readyState==="open"&&this.opts.upgrade...
method _probe (line 464) | _probe(t){let n=this.createTransport(t),r=!1;va.priorWebsocketSuccess=...
method onHandshake (line 464) | onHandshake(t){this._upgrades=this._filterUpgrades(t.upgrades),super.o...
method _filterUpgrades (line 464) | _filterUpgrades(t){const n=[];for(let r=0;r<t.length;r++)~this.transpo...
method constructor (line 464) | constructor(t,n={}){const r=typeof t=="object"?t:n;(!r.transports||r.tra...
function $Y (line 464) | function $Y(e,t="",n){let r=e;n=n||typeof location<"u"&&location,e==null...
function nw (line 464) | function nw(e){return BY&&(e instanceof ArrayBuffer||zY(e))||UY&&e insta...
function jp (line 464) | function jp(e,t){if(!e||typeof e!="object")return!1;if(Array.isArray(e))...
function HY (line 464) | function HY(e){const t=[],n=e.data,r=e;return r.data=wb(n,t),r.attachmen...
function wb (line 464) | function wb(e,t){if(!e)return e;if(nw(e)){const n={_placeholder:!0,num:t...
function qY (line 464) | function qY(e,t){return e.data=Sb(e.data,t),delete e.attachments,e}
function Sb (line 464) | function Sb(e,t){if(!e)return e;if(e&&e._placeholder===!0){if(typeof e.n...
class GY (line 464) | class GY{constructor(t){this.replacer=t}encode(t){return(t.type===_t.EVE...
method constructor (line 464) | constructor(t){this.replacer=t}
method encode (line 464) | encode(t){return(t.type===_t.EVENT||t.type===_t.ACK)&&jp(t)?this.encod...
method encodeAsString (line 464) | encodeAsString(t){let n=""+t.type;return(t.type===_t.BINARY_EVENT||t.t...
method encodeAsBinary (line 464) | encodeAsBinary(t){const n=HY(t),r=this.encodeAsString(n.packet),s=n.bu...
function ZE (line 464) | function ZE(e){return Object.prototype.toString.call(e)==="[object Objec...
class rw (line 464) | class rw extends Pn{constructor(t){super(),this.reviver=t}add(t){let n;i...
method constructor (line 464) | constructor(t){super(),this.reviver=t}
method add (line 464) | add(t){let n;if(typeof t=="string"){if(this.reconstructor)throw new Er...
method decodeString (line 464) | decodeString(t){let n=0;const r={type:Number(t.charAt(0))};if(_t[r.typ...
method tryParse (line 464) | tryParse(t){try{return JSON.parse(t,this.reviver)}catch{return!1}}
method isPayloadValid (line 464) | static isPayloadValid(t,n){switch(t){case _t.CONNECT:return ZE(n);case...
method destroy (line 464) | destroy(){this.reconstructor&&(this.reconstructor.finishedReconstructi...
class JY (line 464) | class JY{constructor(t){this.packet=t,this.buffers=[],this.reconPack=t}t...
method constructor (line 464) | constructor(t){this.packet=t,this.buffers=[],this.reconPack=t}
method takeBinaryData (line 464) | takeBinaryData(t){if(this.buffers.push(t),this.buffers.length===this.r...
method finishedReconstruction (line 464) | finishedReconstruction(){this.reconPack=null,this.buffers=[]}
method PacketType (line 464) | get PacketType(){return _t}
function xs (line 464) | function xs(e,t,n){return e.on(t,n),function(){e.off(t,n)}}
class qO (line 464) | class qO extends Pn{constructor(t,n,r){super(),this.connected=!1,this.re...
method constructor (line 464) | constructor(t,n,r){super(),this.connected=!1,this.recovered=!1,this.re...
method disconnected (line 464) | get disconnected(){return!this.connected}
method subEvents (line 464) | subEvents(){if(this.subs)return;const t=this.io;this.subs=[xs(t,"open"...
method active (line 464) | get active(){return!!this.subs}
method connect (line 464) | connect(){return this.connected?this:(this.subEvents(),this.io._reconn...
method open (line 464) | open(){return this.connect()}
method send (line 464) | send(...t){return t.unshift("message"),this.emit.apply(this,t),this}
method emit (line 464) | emit(t,...n){var r,s,o;if(ZY.hasOwnProperty(t))throw new Error('"'+t.t...
method _registerAckCallback (line 464) | _registerAckCallback(t,n){var r;const s=(r=this.flags.timeout)!==null&...
method emitWithAck (line 464) | emitWithAck(t,...n){return new Promise((r,s)=>{const o=(l,u)=>l?s(l):r...
method _addToQueue (line 464) | _addToQueue(t){let n;typeof t[t.length-1]=="function"&&(n=t.pop());con...
method _drainQueue (line 464) | _drainQueue(t=!1){if(!this.connected||this._queue.length===0)return;co...
method packet (line 464) | packet(t){t.nsp=this.nsp,this.io._packet(t)}
method onopen (line 464) | onopen(){typeof this.auth=="function"?this.auth(t=>{this._sendConnectP...
method _sendConnectPacket (line 464) | _sendConnectPacket(t){this.packet({type:_t.CONNECT,data:this._pid?Obje...
method onerror (line 464) | onerror(t){this.connected||this.emitReserved("connect_error",t)}
method onclose (line 464) | onclose(t,n){this.connected=!1,delete this.id,this.emitReserved("disco...
method _clearAcks (line 464) | _clearAcks(){Object.keys(this.acks).forEach(t=>{if(!this.sendBuffer.so...
method onpacket (line 464) | onpacket(t){if(t.nsp===this.nsp)switch(t.type){case _t.CONNECT:t.data&...
method onevent (line 464) | onevent(t){const n=t.data||[];t.id!=null&&n.push(this.ack(t.id)),this....
method emitEvent (line 464) | emitEvent(t){if(this._anyListeners&&this._anyListeners.length){const n...
method ack (line 464) | ack(t){const n=this;let r=!1;return function(...s){r||(r=!0,n.packet({...
method onack (line 464) | onack(t){const n=this.acks[t.id];typeof n=="function"&&(delete this.ac...
method onconnect (line 464) | onconnect(t,n){this.id=t,this.recovered=n&&this._pid===n,this._pid=n,t...
method emitBuffered (line 464) | emitBuffered(){this.receiveBuffer.forEach(t=>this.emitEvent(t)),this.r...
method ondisconnect (line 464) | ondisconnect(){this.destroy(),this.onclose("io server disconnect")}
method destroy (line 464) | destroy(){this.subs&&(this.subs.forEach(t=>t()),this.subs=void 0),this...
method disconnect (line 464) | disconnect(){return this.connected&&this.packet({type:_t.DISCONNECT}),...
method close (line 464) | close(){return this.disconnect()}
method compress (line 464) | compress(t){return this.flags.compress=t,this}
method volatile (line 464) | get volatile(){return this.flags.volatile=!0,this}
method timeout (line 464) | timeout(t){return this.flags.timeout=t,this}
method onAny (line 464) | onAny(t){return this._anyListeners=this._anyListeners||[],this._anyLis...
method prependAny (line 464) | prependAny(t){return this._anyListeners=this._anyListeners||[],this._a...
method offAny (line 464) | offAny(t){if(!this._anyListeners)return this;if(t){const n=this._anyLi...
method listenersAny (line 464) | listenersAny(){return this._anyListeners||[]}
method onAnyOutgoing (line 464) | onAnyOutgoing(t){return this._anyOutgoingListeners=this._anyOutgoingLi...
method prependAnyOutgoing (line 464) | prependAnyOutgoing(t){return this._anyOutgoingListeners=this._anyOutgo...
method offAnyOutgoing (line 464) | offAnyOutgoing(t){if(!this._anyOutgoingListeners)return this;if(t){con...
method listenersAnyOutgoing (line 464) | listenersAnyOutgoing(){return this._anyOutgoingListeners||[]}
method notifyOutgoingListeners (line 464) | notifyOutgoingListeners(t){if(this._anyOutgoingListeners&&this._anyOut...
function mc (line 464) | function mc(e){e=e||{},this.ms=e.min||100,this.max=e.max||1e4,this.facto...
class Cb (line 464) | class Cb extends Pn{constructor(t,n){var r;super(),this.nsps={},this.sub...
method constructor (line 464) | constructor(t,n){var r;super(),this.nsps={},this.subs=[],t&&typeof t==...
method reconnection (line 464) | reconnection(t){return arguments.length?(this._reconnection=!!t,t||(th...
method reconnectionAttempts (line 464) | reconnectionAttempts(t){return t===void 0?this._reconnectionAttempts:(...
method reconnectionDelay (line 464) | reconnectionDelay(t){var n;return t===void 0?this._reconnectionDelay:(...
method randomizationFactor (line 464) | randomizationFactor(t){var n;return t===void 0?this._randomizationFact...
method reconnectionDelayMax (line 464) | reconnectionDelayMax(t){var n;return t===void 0?this._reconnectionDela...
method timeout (line 464) | timeout(t){return arguments.length?(this._timeout=t,this):this._timeout}
method maybeReconnectOnOpen (line 464) | maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&this.b...
method open (line 464) | open(t){if(~this._readyState.indexOf("open"))return this;this.engine=n...
method connect (line 464) | connect(t){return this.open(t)}
method onopen (line 464) | onopen(){this.cleanup(),this._readyState="open",this.emitReserved("ope...
method onping (line 464) | onping(){this.emitReserved("ping")}
method ondata (line 464) | ondata(t){try{this.decoder.add(t)}catch(n){this.onclose("parse error",...
method ondecoded (line 464) | ondecoded(t){gg(()=>{this.emitReserved("packet",t)},this.setTimeoutFn)}
method onerror (line 464) | onerror(t){this.emitReserved("error",t)}
method socket (line 464) | socket(t,n){let r=this.nsps[t];return r?this._autoConnect&&!r.active&&...
method _destroy (line 464) | _destroy(t){const n=Object.keys(this.nsps);for(const r of n)if(this.ns...
method _packet (line 464) | _packet(t){const n=this.encoder.encode(t);for(let r=0;r<n.length;r++)t...
method cleanup (line 464) | cleanup(){this.subs.forEach(t=>t()),this.subs.length=0,this.decoder.de...
method _close (line 464) | _close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("for...
method disconnect (line 464) | disconnect(){return this._close()}
method onclose (line 464) | onclose(t,n){var r;this.cleanup(),(r=this.engine)===null||r===void 0||...
method reconnect (line 464) | reconnect(){if(this._reconnecting||this.skipReconnect)return this;cons...
method onreconnect (line 464) | onreconnect(){const t=this.backoff.attempts;this._reconnecting=!1,this...
function Tp (line 464) | function Tp(e,t){typeof e=="object"&&(t=e,e=void 0),t=t||{};const n=$Y(e...
function KO (line 464) | function KO(){return{sendText:nt(sX,{invalidateKeys:[["chats","findMessa...
function WO (line 464) | function WO(){return{sendMedia:nt(oX)}}
function iX (line 464) | function iX(){return{sendAudio:nt(aX)}}
function lX (line 464) | function lX({children:e}){const[t]=hd(),{theme:n}=tc(),r=t.get("backgrou...
function ZO (line 464) | function ZO({textareaRef:e,handleTextareaChange:t,textareaHeight:n,lastM...
function tk (line 464) | function tk(){const e=zo("(min-width: 768px)"),t=y.useRef(null),[n]=y.us...
function mX (line 464) | function mX(){return{createChatwoot:nt(gX,{invalidateKeys:[["chatwoot","...
function yX (line 464) | function yX(){const{t:e}=Ve(),{instance:t}=ct(),[,n]=y.useState(!1),{cre...
function bX (line 464) | function bX(){if(nk)return ey;nk=1;var e="SECRET_DO_NOT_PASS_THIS_OR_YOU...
function xX (line 464) | function xX(){if(rk)return ty;rk=1;var e=bX();function t(){}function n()...
function YO (line 464) | function YO(){return sk||(sk=1,Xv.exports=xX()()),Xv.exports}
function XO (line 464) | function XO(){return ok||(ok=1,ny={L:1,M:0,Q:3,H:2}),ny}
function eI (line 464) | function eI(){return ak||(ak=1,ry={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8...
function wX (line 464) | function wX(){if(ik)return sy;ik=1;var e=eI();function t(n){this.mode=e....
function SX (line 464) | function SX(){if(lk)return oy;lk=1;var e=XO();function t(n,r){this.total...
function CX (line 464) | function CX(){if(ck)return ay;ck=1;function e(){this.buffer=new Array,th...
function tI (line 464) | function tI(){if(uk)return iy;uk=1;for(var e={glog:function(n){if(n<1)th...
function nI (line 464) | function nI(){if(dk)return ly;dk=1;var e=tI();function t(n,r){if(n.lengt...
function EX (line 464) | function EX(){if(fk)return cy;fk=1;var e=eI(),t=nI(),n=tI(),r={PATTERN00...
function kX (line 464) | function kX(){if(pk)return uy;pk=1;var e=wX(),t=SX(),n=CX(),r=EX(),s=nI(...
function jX (line 464) | function jX(){if(hk)return sp;hk=1,Object.defineProperty(sp,"__esModule"...
function TX (line 464) | function TX(){if(gk)return wl;gk=1,Object.defineProperty(wl,"__esModule"...
function PX (line 464) | function PX(){const{t:e,i18n:t}=Ve(),n=new Intl.NumberFormat(t.language)...
function AX (line 464) | function AX(e){return IX.includes(e)}
function vg (line 464) | function vg(){const e=nt(zX,{invalidateKeys:[["dify","fetchDefaultSettin...
function WX (line 464) | function WX(){const{t:e}=Ve(),{instance:t}=ct(),{setDefaultSettingsDify:...
function ma (line 473) | function ma(e,t){return typeof e=="function"?e(t):e}
function qr (line 473) | function qr(e,t){return n=>{t.setState(r=>({...r,[e]:ma(n,r[e])}))}}
function yg (line 473) | function yg(e){return e instanceof Function}
function GX (line 473) | function GX(e){return Array.isArray(e)&&e.every(t=>typeof t=="number")}
function lI (line 473) | function lI(e,t){const n=[],r=s=>{s.forEach(o=>{n.push(o);const l=t(o);l...
function ot (line 473) | function ot(e,t,n){let r=[],s;return o=>{let l;n.key&&n.debug&&(l=Date.n...
function at (line 476) | function at(e,t,n,r){return{debug:()=>{var s;return(s=e?.debugAll)!=null...
function JX (line 476) | function JX(e,t,n,r){const s=()=>{var l;return(l=o.getValue())!=null?l:e...
function QX (line 476) | function QX(e,t,n,r){var s,o;const u={...e._getDefaultColumnDef(),...t},...
function vk (line 476) | function vk(e,t,n){var r;let o={id:(r=n.id)!=null?r:t.id,column:t,index:...
function op (line 476) | function op(e,t,n,r){var s,o;let l=0;const u=function(g,x){x===void 0&&(...
function Ts (line 476) | function Ts(e){return e==null||e===""}
function yk (line 476) | function yk(e,t,n){return(e&&e.autoRemove?e.autoRemove(t,n):!1)||typeof ...
function uee (line 476) | function uee(e,t,n){if(!(t!=null&&t.length)||!n)return e;const r=e.filte...
function hee (line 476) | function hee(){if(typeof ip=="boolean")return ip;let e=!1;try{const t={g...
function hy (line 476) | function hy(e){return e.type==="touchstart"}
function Ru (line 476) | function Ru(e,t){return t?t==="center"?e.getCenterVisibleLeafColumns():t...
function vy (line 476) | function vy(e,t){const n=e.getState().rowSelection,r=[],s={},o=function(...
function iw (line 476) | function iw(e,t){var n;return(n=t[e.id])!=null?n:!1}
function Tb (line 476) | function Tb(e,t,n){var r;if(!((r=e.subRows)!=null&&r.length))return!1;le...
function lw (line 476) | function lw(e,t){return e===t?0:e>t?1:-1}
function Na (line 476) | function Na(e){return typeof e=="number"?isNaN(e)||e===1/0||e===-1/0?"":...
function vI (line 476) | function vI(e,t){const n=e.split(Nb).filter(Boolean),r=t.split(Nb).filte...
function _ee (line 476) | function _ee(e){var t,n;const r=[...Mee,...(t=e._features)!=null?t:[]];l...
function Ree (line 476) | function Ree(){return e=>ot(()=>[e.options.data],t=>{const n={rows:[],fl...
function Pee (line 476) | function Pee(e,t,n){return n.options.filterFromLeafRows?Oee(e,t,n):Iee(e...
function Oee (line 476) | function Oee(e,t,n){var r;const s=[],o={},l=(r=n.options.maxLeafRowFilte...
function Iee (line 476) | function Iee(e,t,n){var r;const s=[],o={},l=(r=n.options.maxLeafRowFilte...
function Aee (line 476) | function Aee(){return e=>ot(()=>[e.getPreFilteredRowModel(),e.getState()...
function Dee (line 476) | function Dee(){return e=>ot(()=>[e.getState().grouping,e.getPreGroupedRo...
function Fee (line 476) | function Fee(e,t){const n=new Map;return e.reduce((r,s)=>{const o=`${s.g...
function Lee (line 476) | function Lee(){return e=>ot(()=>[e.getState().sorting,e.getPreSortedRowM...
function bk (line 485) | function bk(e,t){return e?$ee(e)?y.createElement(e,t):e:null}
function $ee (line 485) | function $ee(e){return Bee(e)||typeof e=="function"||zee(e)}
function Bee (line 485) | function Bee(e){return typeof e=="function"&&(()=>{const t=Object.getPro...
function zee (line 485) | function zee(e){return typeof e=="object"&&typeof e.$$typeof=="symbol"&&...
function Uee (line 485) | function Uee(e){const t={state:{},onStateChange:()=>{},renderFallbackVal...
function $a (line 485) | function $a({columns:e,data:t,isLoading:n,loadingMessage:r,noResultsMess...
function SI (line 485) | function SI({difyId:e}){const{t}=Ve(),{instance:n}=ct(),{changeStatusDif...
function CI (line 485) | function CI({initialData:e,onSubmit:t,handleDelete:n,difyId:r,isModal:s=...
function Jee (line 485) | function Jee({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),[r,s]=y.use...
function Xee (line 485) | function Xee({difyId:e,resetTable:t}){const{t:n}=Ve(),{instance:r}=ct(),...
function xk (line 485) | function xk(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function ete (line 485) | function ete({children:e}){const[t]=hd(),[n,r]=y.useState(null),[s,o]=y....
function pte (line 485) | function pte({handleEmojiClick:e}){const{inputIconsMainColor:t}=La(),n=r...
function yte (line 485) | function yte({onSuccess:e}){const{t}=Ve(),{primaryColor:n}=La(),r=on({re...
function bte (line 485) | function bte({isOpen:e,setIsOpen:t}){const[n]=hd(),{t:r}=Ve(),s=dn(),o=l...
function xte (line 485) | function xte(){const[e]=hd(),{backgroundColor:t,textForegroundColor:n,pr...
function wte (line 485) | function wte(){const{instance:e,isLoading:t,error:n}=cw();return t?i.jsx...
function Sk (line 485) | function Sk(){return i.jsx(Yk,{client:_j,children:i.jsx(VM,{children:i.j...
function xg (line 485) | function xg(){const e=nt(Tte,{invalidateKeys:[["evoai","fetchDefaultSett...
function Ote (line 485) | function Ote(){const{t:e}=Ve(),{instance:t}=ct(),{setDefaultSettingsEvoa...
function jI (line 485) | function jI({evoaiId:e}){const{t}=Ve(),{instance:n}=ct(),{changeStatusEv...
function TI (line 485) | function TI({initialData:e,onSubmit:t,handleDelete:n,evoaiId:r,isModal:s...
function Lte (line 485) | function Lte({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),[r,s]=y.use...
function Ute (line 485) | function Ute({evoaiId:e,resetTable:t}){const{t:n}=Ve(),{instance:r}=ct()...
function Ck (line 485) | function Ck(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function wg (line 485) | function wg(){const e=nt(Zte,{invalidateKeys:[["evolutionBot","fetchDefa...
function ene (line 485) | function ene(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{d...
function MI (line 485) | function MI({evolutionBotId:e}){const{t}=Ve(),{instance:n}=ct(),[r,s]=y....
function _I (line 485) | function _I({initialData:e,onSubmit:t,handleDelete:n,evolutionBotId:r,is...
function one (line 485) | function one({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),[r,s]=y.use...
function cne (line 485) | function cne({evolutionBotId:e,resetTable:t}){const{t:n}=Ve(),{instance:...
function Ek (line 485) | function Ek(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function Sg (line 485) | function Sg(){const e=nt(bne,{invalidateKeys:[["flowise","fetchDefaultSe...
function wne (line 485) | function wne(){const{t:e}=Ve(),{instance:t}=ct(),{setDefaultSettingsFlow...
function PI (line 485) | function PI({flowiseId:e}){const{t}=Ve(),{instance:n}=ct(),{changeStatus...
function OI (line 485) | function OI({initialData:e,onSubmit:t,handleDelete:n,flowiseId:r,isModal...
function jne (line 485) | function jne({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),{createFlow...
function _ne (line 485) | function _ne({flowiseId:e,resetTable:t}){const{t:n}=Ve(),{instance:r}=ct...
function kk (line 485) | function kk(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function Cg (line 485) | function Cg(){const e=nt(Dne,{invalidateKeys:[["n8n","fetchDefaultSettin...
function Une (line 485) | function Une(){const{t:e}=Ve(),{instance:t}=ct(),{setDefaultSettingsN8n:...
function AI (line 485) | function AI({n8nId:e}){const{t}=Ve(),{instance:n}=ct(),{changeStatusN8n:...
function DI (line 485) | function DI({initialData:e,onSubmit:t,handleDelete:n,n8nId:r,isModal:s=!...
function Wne (line 485) | function Wne({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),[r,s]=y.use...
function Zne (line 485) | function Zne({n8nId:e,resetTable:t}){const{t:n}=Ve(),{instance:r}=ct(),s...
function jk (line 485) | function jk(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function Md (line 485) | function Md(){const e=nt(ire,{invalidateKeys:[["openai","fetchDefaultSet...
function LI (line 485) | function LI({onCredentialsUpdate:e,showText:t=!0}){const{t:n}=Ve(),{inst...
function hre (line 485) | function hre(){const{t:e}=Ve(),{instance:t}=ct(),{setDefaultSettingsOpen...
function $I (line 485) | function $I({openaiId:e}){const{t}=Ve(),{instance:n}=ct(),{changeStatusO...
function BI (line 485) | function BI({initialData:e,onSubmit:t,handleDelete:n,openaiId:r,isModal:...
function Sre (line 485) | function Sre({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),{createOpen...
function jre (line 485) | function jre({openaiId:e,resetTable:t}){const{t:n}=Ve(),{instance:r}=ct(...
function Tk (line 485) | function Tk(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function Rre (line 485) | function Rre(){return{createProxy:nt(_re,{invalidateKeys:[["proxy","fetc...
function Ore (line 485) | function Ore(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{c...
function Lre (line 485) | function Lre(){return{createRabbitmq:nt(Fre,{invalidateKeys:[["rabbitmq"...
function Bre (line 485) | function Bre(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{c...
function qre (line 485) | function qre(){const{t:e}=Ve(),[t,n]=y.useState(!1),{instance:r}=ct(),{u...
function Qre (line 485) | function Qre(){return{createSqs:nt(Jre,{invalidateKeys:[["sqs","fetchSqs...
function Yre (line 485) | function Yre(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{c...
function Eg (line 485) | function Eg(){const e=nt(ise,{invalidateKeys:[["typebot","fetchDefaultSe...
function use (line 485) | function use(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{s...
function UI (line 485) | function UI({typebotId:e}){const{t}=Ve(),{instance:n}=ct(),[r,s]=y.useSt...
function VI (line 485) | function VI({initialData:e,onSubmit:t,handleDelete:n,typebotId:r,isModal...
function gse (line 485) | function gse({resetTable:e}){const{t}=Ve(),{instance:n}=ct(),{createType...
function bse (line 485) | function bse({typebotId:e,resetTable:t}){const{t:n}=Ve(),{instance:r}=ct...
function Nk (line 485) | function Nk(){const{t:e}=Ve(),t=zo("(min-width: 768px)"),{instance:n}=ct...
function Ese (line 485) | function Ese(){return{createWebhook:nt(Cse,{invalidateKeys:[["webhook","...
function jse (line 485) | function jse(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{c...
function Rse (line 485) | function Rse(){return{createWebsocket:nt(_se,{invalidateKeys:[["websocke...
function Ose (line 485) | function Ose(){const{t:e}=Ve(),{instance:t}=ct(),[n,r]=y.useState(!1),{c...
function Dse (line 485) | function Dse(){const{t:e}=Ve(),t=dn(),{theme:n}=tc(),r=on({resolver:an(A...
function Fse (line 485) | function Fse(){const e=dn(),{theme:t}=tc(),n=()=>{e("/manager")};return ...
method log (line 485) | log(e){this.output("log",e)}
method warn (line 485) | warn(e){this.output("warn",e)}
method error (line 485) | error(e){this.output("error",e)}
method output (line 485) | output(e,t){console&&console[e]&&console[e].apply(console,t)}
class uh (line 485) | class uh{constructor(t){let n=arguments.length>1&&arguments[1]!==void 0?...
method constructor (line 485) | constructor(t){let n=arguments.length>1&&arguments[1]!==void 0?argumen...
method init (line 485) | init(t){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{...
method log (line 485) | log(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=argum...
method warn (line 485) | warn(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=argu...
method error (line 485) | error(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arg...
method deprecate (line 485) | deprecate(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]...
method forward (line 485) | forward(t,n,r,s){return s&&!this.debug?null:(typeof t[0]=="string"&&(t...
method create (line 485) | create(t){return new uh(this.logger,{prefix:`${this.prefix}:${t}:`,......
method clone (line 485) | clone(t){return t=t||this.options,t.prefix=t.prefix||this.prefix,new u...
class kg (line 485) | class kg{constructor(){this.observers={}}on(t,n){return t.split(" ").for...
method constructor (line 485) | constructor(){this.observers={}}
method on (line 485) | on(t,n){return t.split(" ").forEach(r=>{this.observers[r]||(this.obser...
method off (line 485) | off(t,n){if(this.observers[t]){if(!n){delete this.observers[t];return}...
method emit (line 485) | emit(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),s=1;s<n;s++)...
class Kse (line 485) | class Kse{constructor(t){this.capacity=t,this.regExpMap=new Map,this.reg...
method constructor (line 485) | constructor(t){this.capacity=t,this.regExpMap=new Map,this.regExpQueue...
method getRegExp (line 485) | getRegExp(t){const n=this.regExpMap.get(t);if(n!==void 0)return n;cons...
class Ok (line 485) | class Ok extends kg{constructor(t){let n=arguments.length>1&&arguments[1...
method constructor (line 485) | constructor(t){let n=arguments.length>1&&arguments[1]!==void 0?argumen...
method addNamespaces (line 485) | addNamespaces(t){this.options.ns.indexOf(t)<0&&this.options.ns.push(t)}
method removeNamespaces (line 485) | removeNamespaces(t){const n=this.options.ns.indexOf(t);n>-1&&this.opti...
method getResource (line 485) | getResource(t,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arg...
method addResource (line 485) | addResource(t,n,r,s){let o=arguments.length>4&&arguments[4]!==void 0?a...
method addResources (line 485) | addResources(t,n,r){let s=arguments.length>3&&arguments[3]!==void 0?ar...
method addResourceBundle (line 485) | addResourceBundle(t,n,r,s,o){let l=arguments.length>5&&arguments[5]!==...
method removeResourceBundle (line 485) | removeResourceBundle(t,n){this.hasResourceBundle(t,n)&&delete this.dat...
method hasResourceBundle (line 485) | hasResourceBundle(t,n){return this.getResource(t,n)!==void 0}
method getResourceBundle (line 485) | getResourceBundle(t,n){return n||(n=this.options.defaultNS),this.optio...
method getDataByLanguage (line 485) | getDataByLanguage(t){return this.data[t]}
method hasLanguageSomeTranslations (line 485) | hasLanguageSomeTranslations(t){const n=this.getDataByLanguage(t);retur...
method toJSON (line 485) | toJSON(){return this.data}
method addPostProcessor (line 485) | addPostProcessor(e){this.processors[e.name]=e}
method handle (line 485) | handle(e,t,n,r,s){return e.forEach(o=>{this.processors[o]&&(t=this.proce...
class ph (line 485) | class ph extends kg{constructor(t){let n=arguments.length>1&&arguments[1...
method constructor (line 485) | constructor(t){let n=arguments.length>1&&arguments[1]!==void 0?argumen...
method changeLanguage (line 485) | changeLanguage(t){t&&(this.language=t)}
method exists (line 485) | exists(t){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]...
method extractFromKey (line 485) | extractFromKey(t,n){let r=n.nsSeparator!==void 0?n.nsSeparator:this.op...
method translate (line 485) | translate(t,n,r){if(typeof n!="object"&&this.options.overloadTranslati...
method extendTranslation (line 485) | extendTranslation(t,n,r,s,o){var l=this;if(this.i18nFormat&&this.i18nF...
method resolve (line 485) | resolve(t){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1...
method isValidLookup (line 485) | isValidLookup(t){return t!==void 0&&!(!this.options.returnNull&&t===nu...
method getResource (line 485) | getResource(t,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arg...
method getUsedParamsDetails (line 485) | getUsedParamsDetails(){let t=arguments.length>0&&arguments[0]!==void 0...
method hasDefaultValue (line 485) | static hasDefaultValue(t){const n="defaultValue";for(const r in t)if(O...
class Ak (line 485) | class Ak{constructor(t){this.options=t,this.supportedLngs=this.options.s...
method constructor (line 485) | constructor(t){this.options=t,this.supportedLngs=this.options.supporte...
method getScriptPartFromCode (line 485) | getScriptPartFromCode(t){if(t=fh(t),!t||t.indexOf("-")<0)return null;c...
method getLanguagePartFromCode (line 485) | getLanguagePartFromCode(t){if(t=fh(t),!t||t.indexOf("-")<0)return t;co...
method formatLanguageCode (line 485) | formatLanguageCode(t){if(typeof t=="string"&&t.indexOf("-")>-1){const ...
method isSupportedCode (line 485) | isSupportedCode(t){return(this.options.load==="languageOnly"||this.opt...
method getBestMatchFromCodes (line 485) | getBestMatchFromCodes(t){if(!t)return null;let n;return t.forEach(r=>{...
method getFallbackCodes (line 485) | getFallbackCodes(t,n){if(!t)return[];if(typeof t=="function"&&(t=t(n))...
method toResolveHierarchy (line 485) | toResolveHierarchy(t,n){const r=this.getFallbackCodes(n||this.options....
class toe (line 485) | class toe{constructor(t){let n=arguments.length>1&&arguments[1]!==void 0...
method constructor (line 485) | constructor(t){let n=arguments.length>1&&arguments[1]!==void 0?argumen...
method addRule (line 485) | addRule(t,n){this.rules[t]=n}
method clearCache (line 485) | clearCache(){this.pluralRulesCache={}}
method getRule (line 485) | getRule(t){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1...
method needsPlural (line 485) | needsPlural(t){let n=arguments.length>1&&arguments[1]!==void 0?argumen...
method getPluralFormsOfKey (line 485) | getPluralFormsOfKey(t,n){let r=arguments.length>2&&arguments[2]!==void...
method getSuffixes (line 485) | getSuffixes(t){let n=arguments.length>1&&arguments[1]!==void 0?argumen...
method getSuffix (line 485) | getSuffix(t,n){let r=arguments.length>2&&arguments[2]!==void 0?argumen...
method getSuffixRetroCompatible (line 485) | getSuffixRetroCompatible(t,n){const r=t.noAbs?t.plurals(n):t.plurals(M...
method shouldUseIntlApi (line 485) | shouldUseIntlApi(){return!Yse.includes(this.options.compatibilityJSON)}
class noe (line 485) | class noe{constructor(){let t=arguments.length>0&&arguments[0]!==void 0?...
method constructor (line 485) | constructor(){let t=arguments.length>0&&arguments[0]!==void 0?argument...
method init (line 485) | init(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{}...
method reset (line 485) | reset(){this.options&&this.init(this.options)}
method resetRegExp (line 485) | resetRegExp(){const t=(n,r)=>n&&n.source===r?(n.lastIndex=0,n):new Reg...
method interpolate (line 485) | interpolate(t,n,r,s){let o,l,u;const d=this.options&&this.options.inte...
method nest (line 485) | nest(t,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]...
class soe (line 485) | class soe{constructor(){let t=arguments.length>0&&arguments[0]!==void 0?...
method constructor (line 485) | constructor(){let t=arguments.length>0&&arguments[0]!==void 0?argument...
method init (line 485) | init(t){const r=(arguments.length>1&&arguments[1]!==void 0?arguments[1...
method add (line 485) | add(t,n){this.formats[t.toLowerCase().trim()]=n}
method addCached (line 485) | addCached(t,n){this.formats[t.toLowerCase().trim()]=Cl(n)}
method format (line 485) | format(t,n,r){let s=arguments.length>3&&arguments[3]!==void 0?argument...
class aoe (line 485) | class aoe extends kg{constructor(t,n,r){let s=arguments.length>3&&argume...
method constructor (line 485) | constructor(t,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arg...
method queueLoad (line 485) | queueLoad(t,n,r,s){const o={},l={},u={},d={};return t.forEach(f=>{let ...
method loaded (line 485) | loaded(t,n,r){const s=t.split("|"),o=s[0],l=s[1];n&&this.emit("failedL...
method read (line 485) | read(t,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[...
method prepareLoading (line 485) | prepareLoading(t,n){let r=arguments.length>2&&arguments[2]!==void 0?ar...
method load (line 485) | load(t,n,r){this.prepareLoading(t,n,{},r)}
method reload (line 485) | reload(t,n,r){this.prepareLoading(t,n,{reload:!0},r)}
method loadOne (line 485) | loadOne(t){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1...
method saveMissing (line 485) | saveMissing(t,n,r,s,o){let l=arguments.length>5&&arguments[5]!==void 0...
class dd (line 485) | class dd extends kg{constructor(){let t=arguments.length>0&&arguments[0]...
method constructor (line 485) | constructor(){let t=arguments.length>0&&arguments[0]!==void 0?argument...
method init (line 485) | init(){var t=this;let n=arguments.length>0&&arguments[0]!==void 0?argu...
method loadResources (line 485) | loadResources(t){let r=arguments.length>1&&arguments[1]!==void 0?argum...
method reloadResources (line 485) | reloadResources(t,n,r){const s=hu();return typeof t=="function"&&(r=t,...
method use (line 485) | use(t){if(!t)throw new Error("You are passing an undefined module! Ple...
method setResolvedLanguage (line 485) | setResolvedLanguage(t){if(!(!t||!this.languages)&&!(["cimode","dev"].i...
method changeLanguage (line 485) | changeLanguage(t,n){var r=this;this.isLanguageChangingTo=t;const s=hu(...
method getFixedT (line 485) | getFixedT(t,n,r){var s=this;const o=function(l,u){let d;if(typeof u!="...
method t (line 485) | t(){return this.translator&&this.translator.translate(...arguments)}
method exists (line 485) | exists(){return this.translator&&this.translator.exists(...arguments)}
method setDefaultNamespace (line 485) | setDefaultNamespace(t){this.options.defaultNS=t}
method hasLoadedNamespace (line 485) | hasLoadedNamespace(t){let n=arguments.length>1&&arguments[1]!==void 0?...
method loadNamespaces (line 485) | loadNamespaces(t,n){const r=hu();return this.options.ns?(typeof t=="st...
method loadLanguages (line 485) | loadLanguages(t,n){const r=hu();typeof t=="string"&&(t=[t]);const s=th...
method dir (line 485) | dir(t){if(t||(t=this.resolvedLanguage||(this.languages&&this.languages...
method createInstance (line 485) | static createInstance(){let t=arguments.length>0&&arguments[0]!==void ...
method cloneInstance (line 485) | cloneInstance(){let t=arguments.length>0&&arguments[0]!==void 0?argume...
method toJSON (line 485) | toJSON(){return{options:this.options,store:this.store,language:this.la...
FILE: prisma/mysql-migrations/20240809105427_init/migration.sql
type `Instance` (line 2) | CREATE TABLE `Instance` (
type `Session` (line 25) | CREATE TABLE `Session` (
type `Chat` (line 36) | CREATE TABLE `Chat` (
type `Contact` (line 48) | CREATE TABLE `Contact` (
type `Message` (line 61) | CREATE TABLE `Message` (
type `MessageUpdate` (line 86) | CREATE TABLE `MessageUpdate` (
type `Webhook` (line 101) | CREATE TABLE `Webhook` (
type `Chatwoot` (line 117) | CREATE TABLE `Chatwoot` (
type `Label` (line 144) | CREATE TABLE `Label` (
type `Proxy` (line 159) | CREATE TABLE `Proxy` (
type `Setting` (line 176) | CREATE TABLE `Setting` (
type `Rabbitmq` (line 194) | CREATE TABLE `Rabbitmq` (
type `Sqs` (line 207) | CREATE TABLE `Sqs` (
type `Websocket` (line 220) | CREATE TABLE `Websocket` (
type `Typebot` (line 233) | CREATE TABLE `Typebot` (
type `TypebotSession` (line 259) | CREATE TABLE `TypebotSession` (
type `TypebotSetting` (line 276) | CREATE TABLE `TypebotSetting` (
type `Media` (line 297) | CREATE TABLE `Media` (
type `OpenaiCreds` (line 312) | CREATE TABLE `OpenaiCreds` (
type `OpenaiBot` (line 326) | CREATE TABLE `OpenaiBot` (
type `OpenaiSession` (line 359) | CREATE TABLE `OpenaiSession` (
type `OpenaiSetting` (line 374) | CREATE TABLE `OpenaiSetting` (
type `Template` (line 398) | CREATE TABLE `Template` (
type `Dify` (line 414) | CREATE TABLE `Dify` (
type `DifySession` (line 441) | CREATE TABLE `DifySession` (
type `DifySetting` (line 456) | CREATE TABLE `DifySetting` (
FILE: prisma/mysql-migrations/20240813153900_add_unique_index_for_remoted_jid_and_instance_in_contacts/migration.sql
type `Contact_remoteJid_instanceId_key` (line 173) | CREATE UNIQUE INDEX `Contact_remoteJid_instanceId_key` ON `Contact` (`re...
FILE: prisma/mysql-migrations/20240814214314_integrations_unification/migration.sql
type `IntegrationSession` (line 177) | CREATE TABLE `IntegrationSession` (
FILE: prisma/mysql-migrations/20240821203259_add_postgres_migrations/migration.sql
type `GenericBot` (line 160) | CREATE TABLE `GenericBot` (
type `GenericSetting` (line 186) | CREATE TABLE `GenericSetting` (
type `Flowise` (line 207) | CREATE TABLE `Flowise` (
type `FlowiseSetting` (line 233) | CREATE TABLE `FlowiseSetting` (
FILE: prisma/mysql-migrations/20240825131301_change_to_evolution_bot/migration.sql
type `EvolutionBot` (line 166) | CREATE TABLE `EvolutionBot` (
type `EvolutionBotSetting` (line 192) | CREATE TABLE `EvolutionBotSetting` (
FILE: prisma/mysql-migrations/20241001172800_add_message_status/migration.sql
type `IsOnWhatsapp` (line 165) | CREATE TABLE `IsOnWhatsapp` (
FILE: prisma/mysql-migrations/20241108101333_fix_message_status_as_string/migration.sql
type `Pusher` (line 187) | CREATE TABLE `Pusher` (
type `Chat_remoteJid_idx` (line 205) | CREATE INDEX `Chat_remoteJid_idx` ON `Chat`(`remoteJid`)
type `Contact_remoteJid_idx` (line 208) | CREATE INDEX `Contact_remoteJid_idx` ON `Contact`(`remoteJid`)
type `Setting_instanceId_idx` (line 211) | CREATE INDEX `Setting_instanceId_idx` ON `Setting`(`instanceId`)
type `Webhook_instanceId_idx` (line 214) | CREATE INDEX `Webhook_instanceId_idx` ON `Webhook`(`instanceId`)
FILE: prisma/mysql-migrations/20250214181954_add_wavoip_token_column/migration.sql
type `Chat_instanceId_remoteJid_key` (line 175) | CREATE UNIQUE INDEX `Chat_instanceId_remoteJid_key` ON `Chat`(`instanceI...
FILE: prisma/mysql-migrations/20250225180031_add_nats_integration/migration.sql
type `Nats` (line 2) | CREATE TABLE `Nats` (
type `Nats_instanceId_key` (line 14) | CREATE UNIQUE INDEX `Nats_instanceId_key` ON `Nats`(`instanceId`)
FILE: prisma/mysql-migrations/20250514232744_add_n8n_table/migration.sql
type `N8n` (line 2) | CREATE TABLE `N8n` (
type `N8nSetting` (line 31) | CREATE TABLE `N8nSetting` (
type `N8nSetting_instanceId_key` (line 53) | CREATE UNIQUE INDEX `N8nSetting_instanceId_key` ON `N8nSetting`(`instanc...
FILE: prisma/mysql-migrations/20250515211815_add_evoai_table/migration.sql
type `Evoai` (line 2) | CREATE TABLE `Evoai` (
type `EvoaiSetting` (line 30) | CREATE TABLE `EvoaiSetting` (
type `EvoaiSetting_instanceId_key` (line 52) | CREATE UNIQUE INDEX `EvoaiSetting_instanceId_key` ON `EvoaiSetting`(`ins...
FILE: prisma/mysql-migrations/20250918183910_add_kafka_integration/migration.sql
type `Kafka` (line 218) | CREATE TABLE `Kafka` (
FILE: prisma/postgresql-migrations/20240609181238_init/migration.sql
type "Instance" (line 17) | CREATE TABLE "Instance" (
type "Session" (line 34) | CREATE TABLE "Session" (
type "Chat" (line 44) | CREATE TABLE "Chat" (
type "Contact" (line 56) | CREATE TABLE "Contact" (
type "Message" (line 69) | CREATE TABLE "Message" (
type "MessageUpdate" (line 91) | CREATE TABLE "MessageUpdate" (
type "Webhook" (line 106) | CREATE TABLE "Webhook" (
type "Chatwoot" (line 121) | CREATE TABLE "Chatwoot" (
type "Label" (line 145) | CREATE TABLE "Label" (
type "Proxy" (line 159) | CREATE TABLE "Proxy" (
type "Setting" (line 175) | CREATE TABLE "Setting" (
type "Rabbitmq" (line 192) | CREATE TABLE "Rabbitmq" (
type "Sqs" (line 204) | CREATE TABLE "Sqs" (
type "Websocket" (line 216) | CREATE TABLE "Websocket" (
type "Typebot" (line 228) | CREATE TABLE "Typebot" (
type "TypebotSession" (line 251) | CREATE TABLE "TypebotSession" (
type "TypebotSetting" (line 268) | CREATE TABLE "TypebotSetting" (
type "Instance" (line 285) | CREATE UNIQUE INDEX "Instance_name_key" ON "Instance"("name")
type "Instance" (line 288) | CREATE UNIQUE INDEX "Instance_token_key" ON "Instance"("token")
type "Session" (line 291) | CREATE UNIQUE INDEX "Session_sessionId_key" ON "Session"("sessionId")
type "Webhook" (line 294) | CREATE UNIQUE INDEX "Webhook_instanceId_key" ON "Webhook"("instanceId")
type "Chatwoot" (line 297) | CREATE UNIQUE INDEX "Chatwoot_instanceId_key" ON "Chatwoot"("instanceId")
type "Label" (line 300) | CREATE UNIQUE INDEX "Label_labelId_key" ON "Label"("labelId")
type "Proxy" (line 303) | CREATE UNIQUE INDEX "Proxy_instanceId_key" ON "Proxy"("instanceId")
type "Setting" (line 306) | CREATE UNIQUE INDEX "Setting_instanceId_key" ON "Setting"("instanceId")
type "Rabbitmq" (line 309) | CREATE UNIQUE INDEX "Rabbitmq_instanceId_key" ON "Rabbitmq"("instanceId")
type "Sqs" (line 312) | CREATE UNIQUE INDEX "Sqs_instanceId_key" ON "Sqs"("instanceId")
type "Websocket" (line 315) | CREATE UNIQUE INDEX "Websocket_instanceId_key" ON "Websocket"("instanceId")
type "TypebotSetting" (line 318) | CREATE UNIQUE INDEX "TypebotSetting_instanceId_key" ON "TypebotSetting"(...
FILE: prisma/postgresql-migrations/20240712150256_create_templates_table/migration.sql
type "Template" (line 2) | CREATE TABLE "Template" (
type "Template" (line 15) | CREATE UNIQUE INDEX "Template_templateId_key" ON "Template"("templateId")
type "Template" (line 18) | CREATE UNIQUE INDEX "Template_instanceId_key" ON "Template"("instanceId")
FILE: prisma/postgresql-migrations/20240713184337_add_media_table/migration.sql
type "Media" (line 2) | CREATE TABLE "Media" (
type "Media" (line 15) | CREATE UNIQUE INDEX "Media_fileName_key" ON "Media"("fileName")
type "Media" (line 18) | CREATE UNIQUE INDEX "Media_messageId_key" ON "Media"("messageId")
FILE: prisma/postgresql-migrations/20240718121437_add_openai_tables/migration.sql
type "OpenaiCreds" (line 5) | CREATE TABLE "OpenaiCreds" (
type "OpenaiBot" (line 16) | CREATE TABLE "OpenaiBot" (
type "OpenaiSession" (line 46) | CREATE TABLE "OpenaiSession" (
type "OpenaiSetting" (line 61) | CREATE TABLE "OpenaiSetting" (
type "OpenaiCreds" (line 82) | CREATE UNIQUE INDEX "OpenaiCreds_apiKey_key" ON "OpenaiCreds"("apiKey")
type "OpenaiCreds" (line 85) | CREATE UNIQUE INDEX "OpenaiCreds_instanceId_key" ON "OpenaiCreds"("insta...
type "OpenaiBot" (line 88) | CREATE UNIQUE INDEX "OpenaiBot_assistantId_key" ON "OpenaiBot"("assistan...
type "OpenaiSetting" (line 91) | CREATE UNIQUE INDEX "OpenaiSetting_instanceId_key" ON "OpenaiSetting"("i...
FILE: prisma/postgresql-migrations/20240722173259_add_name_column_to_openai_creds/migration.sql
type "OpenaiCreds" (line 12) | CREATE UNIQUE INDEX "OpenaiCreds_name_key" ON "OpenaiCreds"("name")
FILE: prisma/postgresql-migrations/20240723152648_adjusts_in_column_openai_creds/migration.sql
type "OpenaiSetting" (line 8) | CREATE UNIQUE INDEX "OpenaiSetting_openaiCredsId_key" ON "OpenaiSetting"...
FILE: prisma/postgresql-migrations/20240725184147_create_template_table/migration.sql
type "Template" (line 2) | CREATE TABLE "Template" (
type "Template" (line 15) | CREATE UNIQUE INDEX "Template_templateId_key" ON "Template"("templateId")
type "Template" (line 18) | CREATE UNIQUE INDEX "Template_name_key" ON "Template"("name")
FILE: prisma/postgresql-migrations/20240730152156_create_dify_tables/migration.sql
type "Dify" (line 24) | CREATE TABLE "Dify" (
type "DifySession" (line 50) | CREATE TABLE "DifySession" (
type "DifySetting" (line 65) | CREATE TABLE "DifySetting" (
type "DifySetting" (line 85) | CREATE UNIQUE INDEX "DifySetting_instanceId_key" ON "DifySetting"("insta...
FILE: prisma/postgresql-migrations/20240811183328_add_unique_index_for_remoted_jid_and_instance_in_contacts/migration.sql
type "Contact" (line 17) | CREATE UNIQUE INDEX "Contact_remoteJid_instanceId_key" ON "Contact"("rem...
FILE: prisma/postgresql-migrations/20240813003116_make_label_unique_for_instance/migration.sql
type "Label" (line 11) | CREATE UNIQUE INDEX "Label_labelId_instanceId_key" ON "Label"("labelId",...
FILE: prisma/postgresql-migrations/20240814202359_integrations_unification/migration.sql
type "IntegrationSession" (line 61) | CREATE TABLE "IntegrationSession" (
FILE: prisma/postgresql-migrations/20240821171327_add_generic_bot_table/migration.sql
type "GenericBot" (line 2) | CREATE TABLE "GenericBot" (
type "GenericSetting" (line 28) | CREATE TABLE "GenericSetting" (
type "GenericSetting" (line 48) | CREATE UNIQUE INDEX "GenericSetting_instanceId_key" ON "GenericSetting"(...
FILE: prisma/postgresql-migrations/20240821194524_add_flowise_table/migration.sql
type "Flowise" (line 2) | CREATE TABLE "Flowise" (
type "FlowiseSetting" (line 28) | CREATE TABLE "FlowiseSetting" (
type "FlowiseSetting" (line 48) | CREATE UNIQUE INDEX "FlowiseSetting_instanceId_key" ON "FlowiseSetting"(...
FILE: prisma/postgresql-migrations/20240825130616_change_to_evolution_bot/migration.sql
type "EvolutionBot" (line 24) | CREATE TABLE "EvolutionBot" (
type "EvolutionBotSetting" (line 50) | CREATE TABLE "EvolutionBotSetting" (
type "EvolutionBotSetting" (line 70) | CREATE UNIQUE INDEX "EvolutionBotSetting_instanceId_key" ON "EvolutionBo...
FILE: prisma/postgresql-migrations/20240828140837_add_is_on_whatsapp_table/migration.sql
type "is_on_whatsapp" (line 2) | CREATE TABLE "is_on_whatsapp" (
type "is_on_whatsapp" (line 14) | CREATE UNIQUE INDEX "is_on_whatsapp_remote_jid_key" ON "is_on_whatsapp"(...
FILE: prisma/postgresql-migrations/20240830193533_changed_table_case/migration.sql
type "IsOnWhatsapp" (line 11) | CREATE TABLE "IsOnWhatsapp" (
type "IsOnWhatsapp" (line 22) | CREATE UNIQUE INDEX "IsOnWhatsapp_remoteJid_key" ON "IsOnWhatsapp"("remo...
FILE: prisma/postgresql-migrations/20241011085129_create_pusher_table/migration.sql
type "Pusher" (line 2) | CREATE TABLE "Pusher" (
type "Pusher" (line 19) | CREATE UNIQUE INDEX "Pusher_instanceId_key" ON "Pusher"("instanceId")
FILE: prisma/postgresql-migrations/20241017144950_create_index/migration.sql
type "Chat" (line 2) | CREATE INDEX "Chat_instanceId_idx" ON "Chat"("instanceId")
type "Chat" (line 5) | CREATE INDEX "Chat_remoteJid_idx" ON "Chat"("remoteJid")
type "Contact" (line 8) | CREATE INDEX "Contact_remoteJid_idx" ON "Contact"("remoteJid")
type "Contact" (line 11) | CREATE INDEX "Contact_instanceId_idx" ON "Contact"("instanceId")
type "Message" (line 14) | CREATE INDEX "Message_instanceId_idx" ON "Message"("instanceId")
type "MessageUpdate" (line 17) | CREATE INDEX "MessageUpdate_instanceId_idx" ON "MessageUpdate"("instance...
type "MessageUpdate" (line 20) | CREATE INDEX "MessageUpdate_messageId_idx" ON "MessageUpdate"("messageId")
type "Setting" (line 23) | CREATE INDEX "Setting_instanceId_idx" ON "Setting"("instanceId")
type "Webhook" (line 26) | CREATE INDEX "Webhook_instanceId_idx" ON "Webhook"("instanceId")
FILE: prisma/postgresql-migrations/20250225180031_add_nats_integration/migration.sql
type "Nats" (line 2) | CREATE TABLE "Nats" (
type "Nats" (line 14) | CREATE UNIQUE INDEX "Nats_instanceId_key" ON "Nats"("instanceId")
FILE: prisma/postgresql-migrations/20250514232744_add_n8n_table/migration.sql
type "N8n" (line 2) | CREATE TABLE "N8n" (
type "N8nSetting" (line 31) | CREATE TABLE "N8nSetting" (
type "N8nSetting" (line 53) | CREATE UNIQUE INDEX "N8nSetting_instanceId_key" ON "N8nSetting"("instanc...
FILE: prisma/postgresql-migrations/20250515211815_add_evoai_table/migration.sql
type "Evoai" (line 2) | CREATE TABLE "Evoai" (
type "EvoaiSetting" (line 30) | CREATE TABLE "EvoaiSetting" (
type "EvoaiSetting" (line 52) | CREATE UNIQUE INDEX "EvoaiSetting_instanceId_key" ON "EvoaiSetting"("ins...
FILE: prisma/postgresql-migrations/20250918182355_add_kafka_integration/migration.sql
type "Kafka" (line 2) | CREATE TABLE "Kafka" (
type "Kafka" (line 14) | CREATE UNIQUE INDEX "Kafka_instanceId_key" ON "Kafka"("instanceId")
FILE: prisma/postgresql-migrations/20251122003044_add_chat_instance_remotejid_unique/migration.sql
type "Chat" (line 16) | CREATE UNIQUE INDEX "Chat_instanceId_remoteJid_key" ON "Chat"("instanceI...
FILE: runWithProvider.js
function getMigrationsFolder (line 16) | function getMigrationsFolder(provider) {
FILE: src/@types/express.d.ts
type Request (line 5) | interface Request {
FILE: src/api/abstract/abstract.cache.ts
type ICache (line 1) | interface ICache {
FILE: src/api/abstract/abstract.repository.ts
type IInsert (line 6) | type IInsert = { insertCount: number };
type IRepository (line 8) | interface IRepository {
type WriteStore (line 18) | type WriteStore<U> = {
method constructor (line 25) | constructor(configService: ConfigService) {
method insert (line 48) | public insert(data: any, instanceName: string, saveDb = false): Promise<...
method update (line 53) | public update(data: any, instanceName: string, saveDb = false): Promise<...
method find (line 58) | public find(query: any): Promise<any> {
method delete (line 63) | delete(query: any, force?: boolean): Promise<any> {
FILE: src/api/abstract/abstract.router.ts
type DataValidate (line 11) | type DataValidate<T> = {
method constructor (line 21) | constructor() {}
method routerPath (line 22) | public routerPath(path: string, param = true) {
method dataValidate (line 29) | public async dataValidate<T>(args: DataValidate<T>) {
method groupNoValidate (line 65) | public async groupNoValidate<T>(args: DataValidate<T>) {
method groupValidate (line 96) | public async groupValidate<T>(args: DataValidate<T>) {
method inviteCodeValidate (line 146) | public async inviteCodeValidate<T>(args: DataValidate<T>) {
method getParticipantsValidate (line 188) | public async getParticipantsValidate<T>(args: DataValidate<T>) {
FILE: src/api/controllers/business.controller.ts
class BusinessController (line 5) | class BusinessController {
method constructor (line 6) | constructor(private readonly waMonitor: WAMonitoringService) {}
method fetchCatalog (line 8) | public async fetchCatalog({ instanceName }: InstanceDto, data: getCata...
method fetchCollections (line 12) | public async fetchCollections({ instanceName }: InstanceDto, data: get...
FILE: src/api/controllers/call.controller.ts
class CallController (line 5) | class CallController {
method constructor (line 6) | constructor(private readonly waMonitor: WAMonitoringService) {}
method offerCall (line 8) | public async offerCall({ instanceName }: InstanceDto, data: OfferCallD...
FILE: src/api/controllers/chat.controller.ts
class ChatController (line 22) | class ChatController {
method constructor (line 23) | constructor(private readonly waMonitor: WAMonitoringService) {}
method whatsappNumber (line 25) | public async whatsappNumber({ instanceName }: InstanceDto, data: Whats...
method readMessage (line 29) | public async readMessage({ instanceName }: InstanceDto, data: ReadMess...
method archiveChat (line 33) | public async archiveChat({ instanceName }: InstanceDto, data: ArchiveC...
method markChatUnread (line 37) | public async markChatUnread({ instanceName }: InstanceDto, data: MarkC...
method deleteMessage (line 41) | public async deleteMessage({ instanceName }: InstanceDto, data: Delete...
method fetchProfilePicture (line 45) | public async fetchProfilePicture({ instanceName }: InstanceDto, data: ...
method fetchProfile (line 49) | public async fetchProfile({ instanceName }: InstanceDto, data: NumberD...
method fetchContacts (line 53) | public async fetchContacts({ instanceName }: InstanceDto, query: Query...
method getBase64FromMediaMessage (line 57) | public async getBase64FromMediaMessage({ instanceName }: InstanceDto, ...
method fetchMessages (line 61) | public async fetchMessages({ instanceName }: InstanceDto, query: Query...
method fetchStatusMessage (line 65) | public async fetchStatusMessage({ instanceName }: InstanceDto, query: ...
method fetchChats (line 69) | public async fetchChats({ instanceName }: InstanceDto, query: Query<Co...
method findChatByRemoteJid (line 73) | public async findChatByRemoteJid({ instanceName }: InstanceDto, rem
Condensed preview — 346 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,166K chars).
[
{
"path": ".cursor/rules/README.md",
"chars": 4423,
"preview": "# Evolution API Cursor Rules\n\nEste diretório contém as regras e configurações do Cursor IDE para o projeto Evolution API"
},
{
"path": ".cursor/rules/core-development.mdc",
"chars": 7388,
"preview": "---\ndescription: Core development principles and standards for Evolution API development\nglobs:\nalwaysApply: true\n---\n\n#"
},
{
"path": ".cursor/rules/cursor.json",
"chars": 4452,
"preview": "{\n \"version\": \"1.0\",\n \"description\": \"Cursor IDE configuration for Evolution API project\",\n \"rules\": {\n \"general\":"
},
{
"path": ".cursor/rules/project-context.mdc",
"chars": 7515,
"preview": "---\ndescription: Evolution API project-specific context and constraints\nglobs:\nalwaysApply: true\n---\n\n# Evolution API Pr"
},
{
"path": ".cursor/rules/specialized-rules/controller-rules.mdc",
"chars": 9559,
"preview": "---\ndescription: Controller patterns for Evolution API\nglobs:\n - \"src/api/controllers/**/*.ts\"\n - \"src/api/integration"
},
{
"path": ".cursor/rules/specialized-rules/dto-rules.mdc",
"chars": 9017,
"preview": "---\ndescription: DTO patterns and validation for Evolution API\nglobs:\n - \"src/api/dto/**/*.ts\"\n - \"src/api/integration"
},
{
"path": ".cursor/rules/specialized-rules/guard-rules.mdc",
"chars": 10535,
"preview": "---\ndescription: Guard patterns for authentication and authorization in Evolution API\nglobs:\n - \"src/api/guards/**/*.ts"
},
{
"path": ".cursor/rules/specialized-rules/integration-channel-rules.mdc",
"chars": 14945,
"preview": "---\ndescription: Channel integration patterns for Evolution API\nglobs:\n - \"src/api/integrations/channel/**/*.ts\"\nalways"
},
{
"path": ".cursor/rules/specialized-rules/integration-chatbot-rules.mdc",
"chars": 16166,
"preview": "---\ndescription: Chatbot integration patterns for Evolution API\nglobs:\n - \"src/api/integrations/chatbot/**/*.ts\"\nalways"
},
{
"path": ".cursor/rules/specialized-rules/integration-event-rules.mdc",
"chars": 23518,
"preview": "---\ndescription: Event integration patterns for Evolution API\nglobs:\n - \"src/api/integrations/event/**/*.ts\"\nalwaysAppl"
},
{
"path": ".cursor/rules/specialized-rules/integration-storage-rules.mdc",
"chars": 16943,
"preview": "---\ndescription: Storage integration patterns for Evolution API\nglobs:\n - \"src/api/integrations/storage/**/*.ts\"\nalways"
},
{
"path": ".cursor/rules/specialized-rules/route-rules.mdc",
"chars": 11894,
"preview": "---\ndescription: Router patterns for Evolution API\nglobs:\n - \"src/api/routes/**/*.ts\"\nalwaysApply: false\n---\n\n# Evoluti"
},
{
"path": ".cursor/rules/specialized-rules/service-rules.mdc",
"chars": 7278,
"preview": "---\ndescription: Service layer patterns for Evolution API\nglobs:\n - \"src/api/services/**/*.ts\"\n - \"src/api/integration"
},
{
"path": ".cursor/rules/specialized-rules/type-rules.mdc",
"chars": 10661,
"preview": "---\ndescription: Type definitions and interfaces for Evolution API\nglobs:\n - \"src/api/types/**/*.ts\"\n - \"src/@types/**"
},
{
"path": ".cursor/rules/specialized-rules/util-rules.mdc",
"chars": 16474,
"preview": "---\ndescription: Utility functions and helpers for Evolution API\nglobs:\n - \"src/utils/**/*.ts\"\nalwaysApply: false\n---\n\n"
},
{
"path": ".cursor/rules/specialized-rules/validate-rules.mdc",
"chars": 15369,
"preview": "---\ndescription: Validation schemas and patterns for Evolution API\nglobs:\n - \"src/validate/**/*.ts\"\nalwaysApply: false\n"
},
{
"path": ".dockerignore",
"chars": 57,
"preview": ".git\n*Dockerfile*\n*docker-compose*\n.env\nnode_modules\ndist"
},
{
"path": ".eslintignore",
"chars": 19,
"preview": "/node-modules\n/dist"
},
{
"path": ".eslintrc.js",
"chars": 1408,
"preview": "module.exports = {\n parser: '@typescript-eslint/parser',\n parserOptions: {\n project: 'tsconfig.json',\n tsconfigR"
},
{
"path": ".github/ISSUE_TEMPLATE/-en--bug-report.yaml",
"chars": 3421,
"preview": "name: Bug Report\ndescription: Create a report to help us improve.\nlabels:\n - bug\n - en\n # - help wanted\n# Automatical"
},
{
"path": ".github/ISSUE_TEMPLATE/-en--feature-request.yaml",
"chars": 2949,
"preview": "name: Feature Request\ndescription: Suggest ideas for the project.\nlabels:\n - enhancement\n - en\n# Automatically assign "
},
{
"path": ".github/ISSUE_TEMPLATE/-pt--reportar-bug.yaml",
"chars": 3551,
"preview": "name: Relatório de bug\ndescription: Crie um relatório para nos ajudar a melhorar.\nlabels:\n - bug\n - pt-br\n # - help w"
},
{
"path": ".github/ISSUE_TEMPLATE/-pt--solicitar-recurso.yaml",
"chars": 3055,
"preview": "name: Solicitação de recursos\ndescription: Sugira ideias para o projeto.\nlabels:\n - enhancement\n - pt-br\n# Automatical"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 2224,
"preview": "name: 🐛 Bug Report\ndescription: Report a bug or unexpected behavior\ntitle: \"[BUG] \"\nlabels: [\"bug\", \"needs-triage\"]\nassi"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 2533,
"preview": "name: ✨ Feature Request\ndescription: Suggest a new feature or enhancement\ntitle: \"[FEATURE] \"\nlabels: [\"enhancement\", \"n"
},
{
"path": ".github/pull_request_template.md",
"chars": 1561,
"preview": "## 📋 Description\n<!-- Describe your changes in detail -->\n\n## 🔗 Related Issue\n<!-- Link to the issue this PR addresses -"
},
{
"path": ".github/workflows/check_code_quality.yml",
"chars": 838,
"preview": "name: Check Code Quality\n\non: \n pull_request:\n branches: [ main, develop ]\n push:\n branches: [ main, develop ]\n\n"
},
{
"path": ".github/workflows/publish_docker_image.yml",
"chars": 1219,
"preview": "name: Build Docker image\n\non:\n push:\n tags:\n - \"*.*.*\"\n\njobs:\n build_deploy:\n name: Build and Deploy\n ru"
},
{
"path": ".github/workflows/publish_docker_image_homolog.yml",
"chars": 1184,
"preview": "name: Build Docker image\n\non:\n push:\n branches:\n - develop\n\njobs:\n build_deploy:\n name: Build and Deploy\n "
},
{
"path": ".github/workflows/publish_docker_image_latest.yml",
"chars": 1180,
"preview": "name: Build Docker image\n\non:\n push:\n branches:\n - main\n\njobs:\n build_deploy:\n name: Build and Deploy\n r"
},
{
"path": ".github/workflows/security.yml",
"chars": 1222,
"preview": "name: Security Scan\n\non:\n push:\n branches: [ main, develop ]\n pull_request:\n branches: [ main, develop ]\n sched"
},
{
"path": ".gitignore",
"chars": 524,
"preview": "# Repo\nBaileys\n# compiled output\n/dist\n/node_modules\n\n/Docker/.env\n\n# Logs\nlogs/**.json\n*.log\nnpm-debug.log*\npnpm-debug."
},
{
"path": ".gitmodules",
"chars": 128,
"preview": "[submodule \"evolution-manager-v2\"]\n\tpath = evolution-manager-v2\n\turl = https://github.com/EvolutionAPI/evolution-manager"
},
{
"path": ".husky/README.md",
"chars": 1130,
"preview": "# Git Hooks Configuration\n\nEste projeto usa [Husky](https://typicode.github.io/husky/) para automatizar verificações de "
},
{
"path": ".husky/commit-msg",
"chars": 33,
"preview": "npx --no -- commitlint --edit $1\n"
},
{
"path": ".husky/pre-commit",
"chars": 16,
"preview": "npx lint-staged\n"
},
{
"path": ".husky/pre-push",
"chars": 33,
"preview": "npm run build\nnpm run lint:check\n"
},
{
"path": ".prettierrc.js",
"chars": 229,
"preview": "module.exports = {\n semi: true,\n trailingComma: 'all',\n singleQuote: true,\n printWidth: 120,\n arrowParens: 'always'"
},
{
"path": ".vscode/settings.json",
"chars": 463,
"preview": "{\n \"editor.fontSize\": 13,\n \"editor.fontLigatures\": true,\n \"editor.letterSpacing\": 0.5,\n \"editor.smoothScrolling\": tr"
},
{
"path": "AGENTS.md",
"chars": 11344,
"preview": "# Evolution API - AI Agent Guidelines\n\nThis document provides comprehensive guidelines for AI agents (Claude, GPT, Curso"
},
{
"path": "CHANGELOG.md",
"chars": 47283,
"preview": "# 2.3.7 (2025-12-05)\n\n### Features\n\n* **WhatsApp Business Meta Templates**: Add update and delete endpoints for Meta tem"
},
{
"path": "CLAUDE.md",
"chars": 8767,
"preview": "# CLAUDE.md\n\nThis file provides comprehensive guidance to Claude AI when working with the Evolution API codebase.\n\n## Pr"
},
{
"path": "Docker/kafka/docker-compose.yaml",
"chars": 1446,
"preview": "version: '3.3'\n\nservices:\n zookeeper:\n container_name: zookeeper\n image: confluentinc/cp-zookeeper:7.5.0\n envi"
},
{
"path": "Docker/minio/docker-compose.yaml",
"chars": 587,
"preview": "version: '3.3'\n\nservices:\n minio:\n container_name: minio\n image: quay.io/minio/minio\n networks:\n - evolut"
},
{
"path": "Docker/mysql/docker-compose.yaml",
"chars": 427,
"preview": "version: '3.3'\n\nservices:\n mysql:\n container_name: mysql\n image: percona/percona-server:8.0\n networks:\n -"
},
{
"path": "Docker/postgres/docker-compose.yaml",
"chars": 767,
"preview": "version: '3.3'\n\nservices:\n postgres:\n container_name: postgres\n image: postgres:15\n networks:\n - evolutio"
},
{
"path": "Docker/rabbitmq/docker-compose.yaml",
"chars": 501,
"preview": "version: '3.3'\n\nservices:\n rabbitmq:\n container_name: rabbitmq\n image: rabbitmq:management\n environment:\n "
},
{
"path": "Docker/redis/docker-compose.yaml",
"chars": 357,
"preview": "version: '3.3'\n\nservices:\n redis:\n image: redis:latest\n networks:\n - evolution-net\n container_name: redis"
},
{
"path": "Docker/scripts/deploy_database.sh",
"chars": 856,
"preview": "#!/bin/bash\n\nsource ./Docker/scripts/env_functions.sh\n\nif [ \"$DOCKER_ENV\" != \"true\" ]; then\n export_env_vars\nfi\n\nif ["
},
{
"path": "Docker/scripts/env_functions.sh",
"chars": 489,
"preview": "export_env_vars() {\n if [ -f .env ]; then\n while IFS='=' read -r key value; do\n if [[ -z \"$key\" || "
},
{
"path": "Docker/scripts/generate_database.sh",
"chars": 604,
"preview": "#!/bin/bash\n\nsource ./Docker/scripts/env_functions.sh\n\nif [ \"$DOCKER_ENV\" != \"true\" ]; then\n export_env_vars\nfi\n\nif ["
},
{
"path": "Docker/swarm/evolution_api_v2.yaml",
"chars": 5616,
"preview": "version: \"3.7\"\n\nservices:\n evolution_v2:\n image: evoapicloud/evolution-api:v2.3.7\n volumes:\n - evolution_ins"
},
{
"path": "Dockerfile",
"chars": 1613,
"preview": "FROM node:24-alpine AS builder\n\nRUN apk update && \\\n apk add --no-cache git ffmpeg wget curl bash openssl\n\nLABEL vers"
},
{
"path": "Dockerfile.metrics",
"chars": 564,
"preview": "FROM evoapicloud/evolution-api:latest AS base\nWORKDIR /evolution\n\n# Copiamos apenas o necessário para recompilar o dist "
},
{
"path": "Extras/chatwoot/configurar_admin.json",
"chars": 8639,
"preview": "{\n \"name\": \"[Evolution] Configurar Admin\",\n \"nodes\": [\n {\n \"parameters\": {\n \"values\": {\n \"stri"
},
{
"path": "Extras/chatwoot/criador_de_empresas.json",
"chars": 13812,
"preview": "{\n \"name\": \"[Evolution] Criador de Empresas\",\n \"nodes\": [\n {\n \"parameters\": {\n \"httpMethod\": \"POST\",\n "
},
{
"path": "Extras/chatwoot/criador_de_inbox.json",
"chars": 14662,
"preview": "{\n \"name\": \"criador_de_inbox_evo_v2.0\",\n \"nodes\": [\n {\n \"parameters\": {\n \"method\": \"POST\",\n \"url"
},
{
"path": "LICENSE",
"chars": 1793,
"preview": "# Evolution API License\n\nEvolution API is licensed under the Apache License 2.0, with the following additional condition"
},
{
"path": "README.md",
"chars": 9115,
"preview": "<h1 align=\"center\">Evolution Api</h1>\n\n<div align=\"center\">\n\n[=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var tie=TD((ko,jo)=>{function Bk(e,t){for(var n=0;n<t.len"
},
{
"path": "manager/dist/assets/index-DsIrum0U.css",
"chars": 64834,
"preview": "@import\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\";*,:before,:after{box-sizing:bo"
},
{
"path": "manager/dist/index.html",
"chars": 498,
"preview": "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <link rel=\"icon\" type=\"image/png\" href=\"https"
},
{
"path": "manager_install.sh",
"chars": 134,
"preview": "#! /bin/bash\n\ncd evolution-manager-v2\nnpm install\nnpm run build\ncd ..\nrm -rf manager/dist\ncp -r evolution-manager-v2/dis"
},
{
"path": "package.json",
"chars": 5276,
"preview": "{\n \"name\": \"evolution-api\",\n \"version\": \"2.3.7\",\n \"description\": \"Rest api for communication with WhatsApp\",\n \"main\""
},
{
"path": "prisma/mysql-migrations/20240809105427_init/migration.sql",
"chars": 23397,
"preview": "-- CreateTable\nCREATE TABLE `Instance` (\n `id` VARCHAR(191) NOT NULL,\n `name` VARCHAR(255) NOT NULL,\n `connecti"
},
{
"path": "prisma/mysql-migrations/20240813153900_add_unique_index_for_remoted_jid_and_instance_in_contacts/migration.sql",
"chars": 12312,
"preview": "/*\nWarnings:\n- You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be lost."
},
{
"path": "prisma/mysql-migrations/20240814173138_add_ignore_jids_chatwoot/migration.sql",
"chars": 12287,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20240814214314_integrations_unification/migration.sql",
"chars": 13912,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20240821203259_add_postgres_migrations/migration.sql",
"chars": 16895,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20240824162012_add_type_on_integration_sessions/migration.sql",
"chars": 13291,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20240825131301_change_to_evolution_bot/migration.sql",
"chars": 15142,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20241001172800_add_message_status/migration.sql",
"chars": 13777,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20241108101333_fix_message_status_as_string/migration.sql",
"chars": 16488,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20250214181954_add_wavoip_token_column/migration.sql",
"chars": 14628,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/20250225180031_add_nats_integration/migration.sql",
"chars": 605,
"preview": "-- CreateTable\nCREATE TABLE `Nats` (\n `id` VARCHAR(191) NOT NULL,\n `enabled` BOOLEAN NOT NULL DEFAULT false,\n `"
},
{
"path": "prisma/mysql-migrations/20250510035200_add_wavoip_token_to_settings_table/migration.sql",
"chars": 667,
"preview": "/*\nWarnings:\n\n- A unique constraint covering the columns `[remoteJid,instanceId]` on the table `Chat` will be added. If "
},
{
"path": "prisma/mysql-migrations/20250514232744_add_n8n_table/migration.sql",
"chars": 2357,
"preview": "-- CreateTable\nCREATE TABLE `N8n` (\n `id` VARCHAR(191) NOT NULL,\n `enabled` BOOLEAN NOT NULL DEFAULT true,\n `de"
},
{
"path": "prisma/mysql-migrations/20250515211815_add_evoai_table/migration.sql",
"chars": 2342,
"preview": "-- CreateTable\nCREATE TABLE `Evoai` (\n `id` VARCHAR(191) NOT NULL,\n `enabled` BOOLEAN NOT NULL DEFAULT true,\n `"
},
{
"path": "prisma/mysql-migrations/20250516012152_remove_unique_atribute_for_file_name_in_media/migration.sql",
"chars": 66,
"preview": "-- DropIndex\nALTER TABLE `Media` DROP INDEX `Media_fileName_key`;\n"
},
{
"path": "prisma/mysql-migrations/20250612155048_add_coluns_trypebot_tables/migration.sql",
"chars": 286,
"preview": "-- AlterTable\nALTER TABLE `Typebot` ADD COLUMN `splitMessages` BOOLEAN DEFAULT false,\nADD COLUMN `timePerChar` I"
},
{
"path": "prisma/mysql-migrations/20250613143000_add_lid_column_to_is_onwhatsapp/migration.sql",
"chars": 76,
"preview": "-- AlterTable\nALTER TABLE `IsOnWhatsapp` ADD COLUMN `lid` VARCHAR(100);\n"
},
{
"path": "prisma/mysql-migrations/20250918183910_add_kafka_integration/migration.sql",
"chars": 18417,
"preview": "/*\n Warnings:\n\n - You are about to alter the column `createdAt` on the `Chat` table. The data in that column could be "
},
{
"path": "prisma/mysql-migrations/migration_lock.toml",
"chars": 122,
"preview": "# Please do not edit this file manually\n# It should be added in your version-control system (e.g., Git)\nprovider = \"mysq"
},
{
"path": "prisma/mysql-schema.prisma",
"chars": 31023,
"preview": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for "
},
{
"path": "prisma/postgresql-migrations/20240609181238_init/migration.sql",
"chars": 12425,
"preview": "-- CreateEnum\nCREATE TYPE \"InstanceConnectionStatus\" AS ENUM ('open', 'close', 'connecting');\n\n-- CreateEnum\nCREATE TYPE"
},
{
"path": "prisma/postgresql-migrations/20240610144159_create_column_profile_name_instance/migration.sql",
"chars": 80,
"preview": "-- AlterTable\nALTER TABLE \"Instance\" ADD COLUMN \"profileName\" VARCHAR(100);\n"
},
{
"path": "prisma/postgresql-migrations/20240611125754_create_columns_whitelabel_chatwoot/migration.sql",
"chars": 117,
"preview": "-- AlterTable\nALTER TABLE \"Chatwoot\" ADD COLUMN \"logo\" VARCHAR(500),\nADD COLUMN \"organization\" VARCHAR(100);\n"
},
{
"path": "prisma/postgresql-migrations/20240611202817_create_columns_debounce_time_typebot/migration.sql",
"chars": 158,
"preview": "-- AlterTable\nALTER TABLE \"Typebot\" ADD COLUMN \"debounceTime\" INTEGER;\n\n-- AlterTable\nALTER TABLE \"TypebotSetting\" A"
},
{
"path": "prisma/postgresql-migrations/20240712144948_add_business_id_column_to_instances/migration.sql",
"chars": 79,
"preview": "-- AlterTable\nALTER TABLE \"Instance\" ADD COLUMN \"businessId\" VARCHAR(100);\n"
},
{
"path": "prisma/postgresql-migrations/20240712150256_create_templates_table/migration.sql",
"chars": 709,
"preview": "-- CreateTable\nCREATE TABLE \"Template\" (\n \"id\" TEXT NOT NULL,\n \"name\" VARCHAR(255) NOT NULL,\n \"language\" VARCHA"
},
{
"path": "prisma/postgresql-migrations/20240712155950_adjusts_in_templates_table/migration.sql",
"chars": 51,
"preview": "-- DropIndex\nDROP INDEX \"Template_instanceId_key\";\n"
},
{
"path": "prisma/postgresql-migrations/20240712162206_remove_templates_table/migration.sql",
"chars": 256,
"preview": "/*\n Warnings:\n\n - You are about to drop the `Template` table. If the table is not empty, all the data it contains will"
},
{
"path": "prisma/postgresql-migrations/20240712223655_column_fallback_typebot/migration.sql",
"chars": 355,
"preview": "-- AlterEnum\nALTER TYPE \"TriggerOperator\" ADD VALUE 'regex';\n\n-- AlterTable\nALTER TABLE \"TypebotSetting\" ADD COLUMN "
},
{
"path": "prisma/postgresql-migrations/20240712230631_column_ignore_jids_typebot/migration.sql",
"chars": 150,
"preview": "-- AlterTable\nALTER TABLE \"Typebot\" ADD COLUMN \"ignoreJids\" JSONB;\n\n-- AlterTable\nALTER TABLE \"TypebotSetting\" ADD C"
},
{
"path": "prisma/postgresql-migrations/20240713184337_add_media_table/migration.sql",
"chars": 833,
"preview": "-- CreateTable\nCREATE TABLE \"Media\" (\n \"id\" TEXT NOT NULL,\n \"fileName\" VARCHAR(500) NOT NULL,\n \"type\" VARCHAR(1"
},
{
"path": "prisma/postgresql-migrations/20240718121437_add_openai_tables/migration.sql",
"chars": 4400,
"preview": "-- AlterTable\nALTER TABLE \"Message\" ADD COLUMN \"openaiSessionId\" TEXT;\n\n-- CreateTable\nCREATE TABLE \"OpenaiCreds\" (\n"
},
{
"path": "prisma/postgresql-migrations/20240718123923_adjusts_openai_tables/migration.sql",
"chars": 94,
"preview": "-- AlterTable\nALTER TABLE \"OpenaiBot\" ADD COLUMN \"enabled\" BOOLEAN NOT NULL DEFAULT true;\n"
},
{
"path": "prisma/postgresql-migrations/20240722173259_add_name_column_to_openai_creds/migration.sql",
"chars": 370,
"preview": "/*\n Warnings:\n\n - A unique constraint covering the columns `[name]` on the table `OpenaiCreds` will be added. If there"
},
{
"path": "prisma/postgresql-migrations/20240722173518_add_name_column_to_openai_creds/migration.sql",
"chars": 54,
"preview": "-- DropIndex\nDROP INDEX \"OpenaiCreds_instanceId_key\";\n"
},
{
"path": "prisma/postgresql-migrations/20240723152648_adjusts_in_column_openai_creds/migration.sql",
"chars": 289,
"preview": "/*\n Warnings:\n\n - A unique constraint covering the columns `[openaiCredsId]` on the table `OpenaiSetting` will be adde"
},
{
"path": "prisma/postgresql-migrations/20240723200254_add_webhookurl_on_message/migration.sql",
"chars": 78,
"preview": "-- AlterTable\nALTER TABLE \"Message\" ADD COLUMN \"webhookUrl\" VARCHAR(500);\n"
},
{
"path": "prisma/postgresql-migrations/20240725184147_create_template_table/migration.sql",
"chars": 690,
"preview": "-- CreateTable\nCREATE TABLE \"Template\" (\n \"id\" TEXT NOT NULL,\n \"templateId\" VARCHAR(255) NOT NULL,\n \"name\" VARC"
},
{
"path": "prisma/postgresql-migrations/20240725202651_add_webhook_url_template_table/migration.sql",
"chars": 79,
"preview": "-- AlterTable\nALTER TABLE \"Template\" ADD COLUMN \"webhookUrl\" VARCHAR(500);\n"
},
{
"path": "prisma/postgresql-migrations/20240725221646_modify_token_instance_table/migration.sql",
"chars": 46,
"preview": "-- DropIndex\nDROP INDEX \"Instance_token_key\";\n"
},
{
"path": "prisma/postgresql-migrations/20240729115127_modify_trigger_type_openai_typebot_table/migration.sql",
"chars": 56,
"preview": "-- AlterEnum\nALTER TYPE \"TriggerType\" ADD VALUE 'none';\n"
},
{
"path": "prisma/postgresql-migrations/20240729180347_modify_typebot_session_status_openai_typebot_table/migration.sql",
"chars": 1033,
"preview": "/*\n Warnings:\n\n - The values [open] on the enum `TypebotSessionStatus` will be removed. If these variants are still us"
},
{
"path": "prisma/postgresql-migrations/20240730152156_create_dify_tables/migration.sql",
"chars": 3608,
"preview": "/*\n Warnings:\n\n - Changed the type of `botType` on the `OpenaiBot` table. No cast exists, the column would be dropped "
},
{
"path": "prisma/postgresql-migrations/20240801193907_add_column_speech_to_text_openai_setting_table/migration.sql",
"chars": 95,
"preview": "-- AlterTable\nALTER TABLE \"OpenaiSetting\" ADD COLUMN \"speechToText\" BOOLEAN DEFAULT false;\n"
},
{
"path": "prisma/postgresql-migrations/20240803163908_add_column_description_on_integrations_table/migration.sql",
"chars": 238,
"preview": "-- AlterTable\nALTER TABLE \"Dify\" ADD COLUMN \"description\" VARCHAR(255);\n\n-- AlterTable\nALTER TABLE \"OpenaiBot\" ADD C"
},
{
"path": "prisma/postgresql-migrations/20240808210239_add_column_function_url_openaibot_table/migration.sql",
"chars": 257,
"preview": "-- AlterTable\nALTER TABLE \"Instance\" ADD COLUMN \"disconnectionAt\" TIMESTAMP,\nADD COLUMN \"disconnectionObject\" JS"
},
{
"path": "prisma/postgresql-migrations/20240811021156_add_chat_name_column/migration.sql",
"chars": 69,
"preview": "-- AlterTable\nALTER TABLE \"Chat\" ADD COLUMN \"name\" VARCHAR(100);\n"
},
{
"path": "prisma/postgresql-migrations/20240811183328_add_unique_index_for_remoted_jid_and_instance_in_contacts/migration.sql",
"chars": 440,
"preview": "/*\n Warnings:\n\n - A unique constraint covering the columns `[remoteJid,instanceId]` on the table `Contact` will be add"
},
{
"path": "prisma/postgresql-migrations/20240813003116_make_label_unique_for_instance/migration.sql",
"chars": 329,
"preview": "/*\n Warnings:\n\n - A unique constraint covering the columns `[labelId,instanceId]` on the table `Label` will be added. "
},
{
"path": "prisma/postgresql-migrations/20240814173033_add_ignore_jids_chatwoot/migration.sql",
"chars": 72,
"preview": "-- AlterTable\nALTER TABLE \"Chatwoot\" ADD COLUMN \"ignoreJids\" JSONB;\n"
},
{
"path": "prisma/postgresql-migrations/20240814202359_integrations_unification/migration.sql",
"chars": 3471,
"preview": "/*\n Warnings:\n\n - You are about to drop the column `difySessionId` on the `Message` table. All the data in the column "
},
{
"path": "prisma/postgresql-migrations/20240817110155_add_trigger_type_advanced/migration.sql",
"chars": 60,
"preview": "-- AlterEnum\nALTER TYPE \"TriggerType\" ADD VALUE 'advanced';\n"
},
{
"path": "prisma/postgresql-migrations/20240819154941_add_context_to_integration_session/migration.sql",
"chars": 79,
"preview": "-- AlterTable\nALTER TABLE \"IntegrationSession\" ADD COLUMN \"context\" JSONB;\n"
},
{
"path": "prisma/postgresql-migrations/20240821120816_bot_id_integration_session/migration.sql",
"chars": 858,
"preview": "/*\n Warnings:\n\n - You are about to drop the column `difyId` on the `IntegrationSession` table. All the data in the col"
},
{
"path": "prisma/postgresql-migrations/20240821171327_add_generic_bot_table/migration.sql",
"chars": 2040,
"preview": "-- CreateTable\nCREATE TABLE \"GenericBot\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT true,\n \"des"
},
{
"path": "prisma/postgresql-migrations/20240821194524_add_flowise_table/migration.sql",
"chars": 2037,
"preview": "-- CreateTable\nCREATE TABLE \"Flowise\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT true,\n \"descri"
},
{
"path": "prisma/postgresql-migrations/20240824161333_add_type_on_integration_sessions/migration.sql",
"chars": 83,
"preview": "-- AlterTable\nALTER TABLE \"IntegrationSession\" ADD COLUMN \"type\" VARCHAR(100);\n"
},
{
"path": "prisma/postgresql-migrations/20240825130616_change_to_evolution_bot/migration.sql",
"chars": 2717,
"preview": "/*\n Warnings:\n\n - You are about to drop the `GenericBot` table. If the table is not empty, all the data it contains wi"
},
{
"path": "prisma/postgresql-migrations/20240828140837_add_is_on_whatsapp_table/migration.sql",
"chars": 424,
"preview": "-- CreateTable\nCREATE TABLE \"is_on_whatsapp\" (\n \"id\" TEXT NOT NULL,\n \"remote_jid\" VARCHAR(100) NOT NULL,\n \"name"
},
{
"path": "prisma/postgresql-migrations/20240828141556_remove_name_column_from_on_whatsapp_table/migration.sql",
"chars": 199,
"preview": "/*\n Warnings:\n\n - You are about to drop the column `name` on the `is_on_whatsapp` table. All the data in the column wi"
},
{
"path": "prisma/postgresql-migrations/20240830193533_changed_table_case/migration.sql",
"chars": 576,
"preview": "/*\n Warnings:\n\n - You are about to drop the `is_on_whatsapp` table. If the table is not empty, all the data it contain"
},
{
"path": "prisma/postgresql-migrations/20240906202019_add_headers_on_webhook_config/migration.sql",
"chars": 68,
"preview": "-- AlterTable\nALTER TABLE \"Webhook\" ADD COLUMN \"headers\" JSONB;\n"
},
{
"path": "prisma/postgresql-migrations/20241001180457_add_message_status/migration.sql",
"chars": 69,
"preview": "-- AlterTable\nALTER TABLE \"Message\" ADD COLUMN \"status\" INTEGER;\n"
},
{
"path": "prisma/postgresql-migrations/20241006130306_alter_status_on_message_table/migration.sql",
"chars": 132,
"preview": "-- AlterTable\nALTER TABLE \"Message\"\nALTER COLUMN \"status\"\nSET\n DATA TYPE VARCHAR(30);\n\nUPDATE \"Message\" SET \"status\" "
},
{
"path": "prisma/postgresql-migrations/20241007164026_add_unread_messages_on_chat_table/migration.sql",
"chars": 93,
"preview": "-- AlterTable\nALTER TABLE \"Chat\" ADD COLUMN \"unreadMessages\" INTEGER NOT NULL DEFAULT 0;\n"
},
{
"path": "prisma/postgresql-migrations/20241011085129_create_pusher_table/migration.sql",
"chars": 755,
"preview": "-- CreateTable\nCREATE TABLE \"Pusher\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT false,\n \"appId\""
},
{
"path": "prisma/postgresql-migrations/20241011100803_split_messages_and_time_per_char_integrations/migration.sql",
"chars": 1152,
"preview": "-- AlterTable\nALTER TABLE \"Dify\" ADD COLUMN \"splitMessages\" BOOLEAN DEFAULT false,\nADD COLUMN \"timePerChar\" INTE"
},
{
"path": "prisma/postgresql-migrations/20241017144950_create_index/migration.sql",
"chars": 743,
"preview": "-- CreateIndex\nCREATE INDEX \"Chat_instanceId_idx\" ON \"Chat\"(\"instanceId\");\n\n-- CreateIndex\nCREATE INDEX \"Chat_remoteJid_"
},
{
"path": "prisma/postgresql-migrations/20250116001415_add_wavoip_token_to_settings_table/migration.sql",
"chars": 267,
"preview": "/*\nWarnings:\n\n- A unique constraint covering the columns `[remoteJid,instanceId]` on the table `Chat` will be added. If "
},
{
"path": "prisma/postgresql-migrations/20250225180031_add_nats_integration/migration.sql",
"chars": 557,
"preview": "-- CreateTable\nCREATE TABLE \"Nats\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT false,\n \"events\" "
},
{
"path": "prisma/postgresql-migrations/20250514232744_add_n8n_table/migration.sql",
"chars": 2180,
"preview": "-- CreateTable\nCREATE TABLE \"N8n\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT true,\n \"descriptio"
},
{
"path": "prisma/postgresql-migrations/20250515211815_add_evoai_table/migration.sql",
"chars": 2169,
"preview": "-- CreateTable\nCREATE TABLE \"Evoai\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT true,\n \"descript"
},
{
"path": "prisma/postgresql-migrations/20250516012152_remove_unique_atribute_for_file_name_in_media/migration.sql",
"chars": 46,
"preview": "-- DropIndex\nDROP INDEX \"Media_fileName_key\";\n"
},
{
"path": "prisma/postgresql-migrations/20250612155048_add_coluns_trypebot_tables/migration.sql",
"chars": 286,
"preview": "-- AlterTable\nALTER TABLE \"Typebot\" ADD COLUMN \"splitMessages\" BOOLEAN DEFAULT false,\nADD COLUMN \"timePerChar\" I"
},
{
"path": "prisma/postgresql-migrations/20250613143000_add_lid_column_to_is_onwhatsapp/migration.sql",
"chars": 76,
"preview": "-- AlterTable\nALTER TABLE \"IsOnWhatsapp\" ADD COLUMN \"lid\" VARCHAR(100);\n"
},
{
"path": "prisma/postgresql-migrations/20250918182355_add_kafka_integration/migration.sql",
"chars": 563,
"preview": "-- CreateTable\nCREATE TABLE \"Kafka\" (\n \"id\" TEXT NOT NULL,\n \"enabled\" BOOLEAN NOT NULL DEFAULT false,\n \"events\""
},
{
"path": "prisma/postgresql-migrations/20251122003044_add_chat_instance_remotejid_unique/migration.sql",
"chars": 471,
"preview": "-- 1. Cleanup: Remove duplicate chats, keeping the most recently updated one\nDELETE FROM \"Chat\"\nWHERE id IN (\n SELECT i"
},
{
"path": "prisma/postgresql-migrations/migration_lock.toml",
"chars": 127,
"preview": "# Please do not edit this file manually\n# It should be added in your version-control system (e.g., Git)\nprovider = \"post"
},
{
"path": "prisma/postgresql-schema.prisma",
"chars": 31682,
"preview": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for "
},
{
"path": "prisma/psql_bouncer-schema.prisma",
"chars": 31701,
"preview": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for "
},
{
"path": "prometheus.yml.example",
"chars": 2293,
"preview": "# Prometheus configuration example for Evolution API\n# Copy this file to prometheus.yml and adjust the settings\n\nglobal:"
},
{
"path": "runWithProvider.js",
"chars": 1660,
"preview": "const dotenv = require('dotenv');\nconst { execSync } = require('child_process');\nconst { existsSync } = require('fs');\n\n"
},
{
"path": "src/@types/express.d.ts",
"chars": 135,
"preview": "import { Multer } from 'multer';\n\ndeclare global {\n namespace Express {\n interface Request {\n file?: Multer.Fil"
},
{
"path": "src/api/abstract/abstract.cache.ts",
"chars": 484,
"preview": "export interface ICache {\n get(key: string): Promise<any>;\n\n hGet(key: string, field: string): Promise<any>;\n\n set(ke"
},
{
"path": "src/api/abstract/abstract.repository.ts",
"chars": 1917,
"preview": "import { ConfigService, Database } from '@config/env.config';\nimport { ROOT_DIR } from '@config/path.config';\nimport { e"
},
{
"path": "src/api/abstract/abstract.router.ts",
"chars": 6183,
"preview": "import 'express-async-errors';\n\nimport { GetParticipant, GroupInvite } from '@api/dto/group.dto';\nimport { InstanceDto }"
},
{
"path": "src/api/controllers/business.controller.ts",
"chars": 669,
"preview": "import { getCatalogDto, getCollectionsDto } from '@api/dto/business.dto';\nimport { InstanceDto } from '@api/dto/instance"
},
{
"path": "src/api/controllers/call.controller.ts",
"chars": 429,
"preview": "import { OfferCallDto } from '@api/dto/call.dto';\nimport { InstanceDto } from '@api/dto/instance.dto';\nimport { WAMonito"
},
{
"path": "src/api/controllers/chat.controller.ts",
"chars": 4692,
"preview": "import {\n ArchiveChatDto,\n BlockUserDto,\n DeleteMessage,\n getBase64FromMediaMessageDto,\n MarkChatUnreadDto,\n Numbe"
},
{
"path": "src/api/controllers/group.controller.ts",
"chars": 3368,
"preview": "import {\n AcceptGroupInvite,\n CreateGroupDto,\n GetParticipant,\n GroupDescriptionDto,\n GroupInvite,\n GroupJid,\n Gr"
},
{
"path": "src/api/controllers/instance.controller.ts",
"chars": 17118,
"preview": "import { InstanceDto, SetPresenceDto } from '@api/dto/instance.dto';\nimport { ChatwootService } from '@api/integrations/"
},
{
"path": "src/api/controllers/label.controller.ts",
"chars": 577,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { HandleLabelDto } from '@api/dto/label.dto';\nimport { WAMon"
},
{
"path": "src/api/controllers/proxy.controller.ts",
"chars": 2271,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { ProxyDto } from '@api/dto/proxy.dto';\nimport { WAMonitorin"
},
{
"path": "src/api/controllers/sendMessage.controller.ts",
"chars": 4133,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport {\n SendAudioDto,\n SendButtonsDto,\n SendContactDto,\n Send"
},
{
"path": "src/api/controllers/settings.controller.ts",
"chars": 549,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { SettingsDto } from '@api/dto/settings.dto';\nimport { Setti"
},
{
"path": "src/api/controllers/template.controller.ts",
"chars": 911,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { TemplateDto } from '@api/dto/template.dto';\nimport { Templ"
},
{
"path": "src/api/dto/business.dto.ts",
"chars": 206,
"preview": "export class NumberDto {\n number: string;\n}\n\nexport class getCatalogDto {\n number?: string;\n limit?: number;\n cursor"
},
{
"path": "src/api/dto/call.dto.ts",
"chars": 138,
"preview": "export class Metadata {\n number: string;\n}\n\nexport class OfferCallDto extends Metadata {\n isVideo?: boolean;\n callDur"
},
{
"path": "src/api/dto/chat.dto.ts",
"chars": 2260,
"preview": "import {\n proto,\n WAPresence,\n WAPrivacyGroupAddValue,\n WAPrivacyOnlineValue,\n WAPrivacyValue,\n WAReadReceiptsValu"
},
{
"path": "src/api/dto/chatbot.dto.ts",
"chars": 203,
"preview": "export class Session {\n remoteJid?: string;\n sessionId?: string;\n status?: string;\n createdAt?: number;\n updateAt?:"
},
{
"path": "src/api/dto/group.dto.ts",
"chars": 1043,
"preview": "export class CreateGroupDto {\n subject: string;\n participants: string[];\n description?: string;\n promoteParticipants"
},
{
"path": "src/api/dto/instance.dto.ts",
"chars": 1513,
"preview": "import { IntegrationDto } from '@api/integrations/integration.dto';\nimport { JsonValue } from '@prisma/client/runtime/li"
},
{
"path": "src/api/dto/label.dto.ts",
"chars": 197,
"preview": "export class LabelDto {\n id?: string;\n name: string;\n color: string;\n predefinedId?: string;\n}\n\nexport class HandleL"
},
{
"path": "src/api/dto/proxy.dto.ts",
"chars": 141,
"preview": "export class ProxyDto {\n enabled?: boolean;\n host: string;\n port: string;\n protocol: string;\n username?: string;\n "
},
{
"path": "src/api/dto/sendMessage.dto.ts",
"chars": 3192,
"preview": "import { proto, WAPresence } from 'baileys';\n\nexport class Quoted {\n key: proto.IMessageKey;\n message: proto.IMessage;"
},
{
"path": "src/api/dto/settings.dto.ts",
"chars": 228,
"preview": "export class SettingsDto {\n rejectCall?: boolean;\n msgCall?: string;\n groupsIgnore?: boolean;\n alwaysOnline?: boolea"
},
{
"path": "src/api/dto/template.dto.ts",
"chars": 411,
"preview": "export class TemplateDto {\n name: string;\n category: string;\n allowCategoryChange: boolean;\n language: string;\n com"
},
{
"path": "src/api/guards/auth.guard.ts",
"chars": 1655,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { prismaRepository } from '@api/server.module';\nimport { Aut"
},
{
"path": "src/api/guards/instance.guard.ts",
"chars": 1936,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { cache, prismaRepository, waMonitor } from '@api/server.mod"
},
{
"path": "src/api/guards/telemetry.guard.ts",
"chars": 290,
"preview": "import { sendTelemetry } from '@utils/sendTelemetry';\nimport { NextFunction, Request, Response } from 'express';\n\nclass "
},
{
"path": "src/api/integrations/channel/channel.controller.ts",
"chars": 2786,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { ProviderFiles } from '@api/provider/sessions';\nimport { Pr"
},
{
"path": "src/api/integrations/channel/channel.router.ts",
"chars": 564,
"preview": "import { Router } from 'express';\n\nimport { EvolutionRouter } from './evolution/evolution.router';\nimport { MetaRouter }"
},
{
"path": "src/api/integrations/channel/evolution/evolution.channel.service.ts",
"chars": 27865,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport {\n MediaMessage,\n Options,\n SendAudioDto,\n SendButtonsDt"
},
{
"path": "src/api/integrations/channel/evolution/evolution.controller.ts",
"chars": 1183,
"preview": "import { PrismaRepository } from '@api/repository/repository.service';\nimport { WAMonitoringService } from '@api/service"
},
{
"path": "src/api/integrations/channel/evolution/evolution.router.ts",
"chars": 620,
"preview": "import { RouterBroker } from '@api/abstract/abstract.router';\nimport { evolutionController } from '@api/server.module';\n"
},
{
"path": "src/api/integrations/channel/meta/meta.controller.ts",
"chars": 2145,
"preview": "import { PrismaRepository } from '@api/repository/repository.service';\nimport { WAMonitoringService } from '@api/service"
},
{
"path": "src/api/integrations/channel/meta/meta.router.ts",
"chars": 919,
"preview": "import { RouterBroker } from '@api/abstract/abstract.router';\nimport { metaController } from '@api/server.module';\nimpor"
},
{
"path": "src/api/integrations/channel/meta/whatsapp.business.service.ts",
"chars": 59143,
"preview": "import { NumberBusiness } from '@api/dto/chat.dto';\nimport {\n ContactMessage,\n MediaMessage,\n Options,\n SendAudioDto"
},
{
"path": "src/api/integrations/channel/whatsapp/baileys.controller.ts",
"chars": 2149,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { WAMonitoringService } from '@api/services/monitor.service'"
},
{
"path": "src/api/integrations/channel/whatsapp/baileys.router.ts",
"chars": 4080,
"preview": "import { RouterBroker } from '@api/abstract/abstract.router';\nimport { InstanceDto } from '@api/dto/instance.dto';\nimpor"
},
{
"path": "src/api/integrations/channel/whatsapp/baileysMessage.processor.ts",
"chars": 2485,
"preview": "import { Logger } from '@config/logger.config';\nimport { BaileysEventMap, MessageUpsertType, WAMessage } from 'baileys';"
},
{
"path": "src/api/integrations/channel/whatsapp/voiceCalls/transport.type.ts",
"chars": 2692,
"preview": "import { BinaryNode, Contact, JidWithDevice, proto, WAConnectionState } from 'baileys';\n\nexport interface ServerToClient"
},
{
"path": "src/api/integrations/channel/whatsapp/voiceCalls/useVoiceCallsBaileys.ts",
"chars": 5722,
"preview": "import { ConnectionState, WAConnectionState, WASocket } from 'baileys';\nimport { io, Socket } from 'socket.io-client';\n\n"
},
{
"path": "src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts",
"chars": 176027,
"preview": "import { getCollectionsDto } from '@api/dto/business.dto';\nimport { OfferCallDto } from '@api/dto/call.dto';\nimport {\n "
},
{
"path": "src/api/integrations/chatbot/base-chatbot.controller.ts",
"chars": 29029,
"preview": "import { IgnoreJidDto } from '@api/dto/chatbot.dto';\nimport { InstanceDto } from '@api/dto/instance.dto';\nimport { Prism"
},
{
"path": "src/api/integrations/chatbot/base-chatbot.dto.ts",
"chars": 1055,
"preview": "import { TriggerOperator, TriggerType } from '@prisma/client';\n\n/**\n * Base DTO for all chatbot integrations\n * Contains"
},
{
"path": "src/api/integrations/chatbot/base-chatbot.service.ts",
"chars": 12926,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { PrismaRepository } from '@api/repository/repository.servic"
},
{
"path": "src/api/integrations/chatbot/chatbot.controller.ts",
"chars": 5632,
"preview": "import { InstanceDto } from '@api/dto/instance.dto';\nimport { PrismaRepository } from '@api/repository/repository.servic"
},
{
"path": "src/api/integrations/chatbot/chatbot.router.ts",
"chars": 1325,
"preview": "import { ChatwootRouter } from '@api/integrations/chatbot/chatwoot/routes/chatwoot.router';\nimport { DifyRouter } from '"
}
]
// ... and 146 more files (download for full content)
About this extraction
This page contains the full source code of the EvolutionAPI/evolution-api GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 346 files (2.9 MB), approximately 782.1k tokens, and a symbol index with 3234 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.