@fayz-ai/plugin-conversations 0.17.1 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/index.js +388 -78
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/views/MediaBubble.d.ts +8 -0
- package/dist/views/MediaBubble.d.ts.map +1 -0
- package/dist/views/MessageThread.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -10,6 +10,8 @@ export declare const MIGRATION_008_DAR_POR_VISTA_E_UMA_DECISAO = "-- -----------
|
|
|
10
10
|
export declare const MIGRATION_009_A_MENSAGEM_INTEIRA_ATRAVESSA_O_REALTIME = "-- ---------------------------------------------------------------------------\n-- 009_a_mensagem_inteira_atravessa_o_realtime.sql\n--\n-- \u2500\u2500 o buraco \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- O vigia da caixa assinava `plg_conversation_messages`, recebia `SUBSCRIBED`\n-- do servidor, e nunca recebia um \u00FAnico evento. Nenhum erro, nenhum aviso: a\n-- assinatura dizia que estava tudo bem e n\u00E3o chegava nada.\n--\n-- A causa \u00E9 a combina\u00E7\u00E3o de duas coisas que, sozinhas, est\u00E3o certas:\n--\n-- 1. a tabela tem RLS ligada, como toda tabela desta base;\n-- 2. a tabela estava com `REPLICA IDENTITY` no padr\u00E3o \u2014 s\u00F3 a chave prim\u00E1ria.\n--\n-- O Realtime do Supabase aplica a POL\u00CDTICA DE LEITURA do usu\u00E1rio a cada evento\n-- antes de entreg\u00E1-lo. Para isso ele precisa da linha inteira: a pol\u00EDtica fala\n-- de `tenant_id`, e `tenant_id` n\u00E3o \u00E9 a chave prim\u00E1ria. Com s\u00F3 a PK no WAL, n\u00E3o\n-- h\u00E1 o que avaliar \u2014 e o evento \u00E9 descartado sem ru\u00EDdo.\n--\n-- `plg_conversations` j\u00E1 estava `FULL` (006). A tabela de MENSAGENS ficou de\n-- fora daquela migration, e \u00E9 justamente ela que o vigia escuta.\n--\n-- \u2500\u2500 por que isso \u00E9 caro e ainda assim certo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- `FULL` faz o WAL carregar a linha inteira em cada UPDATE e DELETE, n\u00E3o s\u00F3 as\n-- colunas mudadas. Numa tabela de mensagens isso \u00E9 peso real.\n--\n-- A alternativa \u2014 desligar a RLS para o Realtime enxergar \u2014 trocaria um custo\n-- de disco por um vazamento: as mensagens de uma casa chegariam ao navegador\n-- de outra. Entre pagar WAL e vazar conversa, paga-se o WAL.\n--\n-- Idempotente e replay-safe.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_conversation_messages REPLICA IDENTITY FULL;\n\n-- Garante a publica\u00E7\u00E3o tamb\u00E9m \u2014 uma tabela com identidade cheia e fora da\n-- publica\u00E7\u00E3o continua sem emitir nada, e o sintoma seria id\u00EAntico.\nDO $$\nBEGIN\n IF NOT EXISTS (\n SELECT 1 FROM pg_publication_tables\n WHERE pubname = 'supabase_realtime'\n AND schemaname = 'public'\n AND tablename = 'plg_conversation_messages'\n ) THEN\n EXECUTE 'ALTER PUBLICATION supabase_realtime ADD TABLE public.plg_conversation_messages';\n END IF;\nEND $$;\n";
|
|
11
11
|
export declare const MIGRATION_010_A_CHEGADA_E_ANUNCIADA_POR_CONTA = "-- ---------------------------------------------------------------------------\n-- 010_a_chegada_e_anunciada_por_conta.sql\n--\n-- \u2500\u2500 por que `postgres_changes` nunca funcionou aqui \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- O vigia assinava a TABELA de mensagens e recebia `SUBSCRIBED` do servidor.\n-- Nenhum evento chegava. Nenhum erro, nenhum aviso \u2014 a assinatura dizia que\n-- estava tudo bem.\n--\n-- O Realtime aplica a pol\u00EDtica de leitura a cada evento antes de entreg\u00E1-lo. A\n-- pol\u00EDtica desta base resolve o tenant por, nesta ordem:\n--\n-- \u2460 a claim `tenant_id` do JWT\n-- \u2461 o CABE\u00C7ALHO da requisi\u00E7\u00E3o (`app.requested_tenant()`)\n-- \u2462 a filia\u00E7\u00E3o \u00FAnica, quando a pessoa s\u00F3 tem uma\n--\n-- O Realtime manda o JWT e N\u00C3O manda cabe\u00E7alho. E o JWT desta casa n\u00E3o carrega\n-- `tenant_id` \u2014 a conta ativa \u00E9 escolhida por cabe\u00E7alho, porque a mesma pessoa\n-- atende sete contas. Sobra \u2462, que devolve nulo para quem tem mais de uma.\n--\n-- Resultado: a pol\u00EDtica recusa, o evento \u00E9 descartado em sil\u00EAncio, e o defeito\n-- parece \"o realtime n\u00E3o funciona\" quando na verdade \u00E9 \"o realtime n\u00E3o sabe em\n-- que conta voc\u00EA est\u00E1\".\n--\n-- \u2500\u2500 a sa\u00EDda: anunciar, em vez de espiar a tabela \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- Broadcast n\u00E3o passa pela RLS da tabela: o servidor entrega a quem est\u00E1 no\n-- T\u00D3PICO. Ent\u00E3o o t\u00F3pico carrega a conta no nome \u2014 `conversas:<tenant>` \u2014 e\n-- quem escuta j\u00E1 teve de saber em que conta est\u00E1 para montar o nome.\n--\n-- Isso inverte a depend\u00EAncia de forma saud\u00E1vel: em vez de o banco adivinhar o\n-- contexto do navegador, o navegador declara o contexto que j\u00E1 tem.\n--\n-- \u2500\u2500 o que vai no an\u00FAncio \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- O M\u00CDNIMO para decidir: id da conversa, canal, e um trecho. N\u00E3o a mensagem\n-- inteira \u2014 um broadcast \u00E9 entregue a todos do t\u00F3pico, e mandar o corpo\n-- completo por ali seria espalhar conversa por um caminho que n\u00E3o \u00E9 o que\n-- guarda conversa. Quem quiser o texto l\u00EA a tabela, com RLS, como sempre.\n--\n-- Idempotente e replay-safe.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.plg_conversations_anunciar_chegada()\nRETURNS trigger\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path = ''\nAS $$\nDECLARE\n v_nome text;\nBEGIN\n -- S\u00F3 o que CHEGA. A resposta que o operador manda tamb\u00E9m \u00E9 um INSERT, e\n -- anunci\u00E1-la faria o sistema apitar para quem acabou de digitar.\n IF NEW.direction IS DISTINCT FROM 'inbound' THEN\n RETURN NEW;\n END IF;\n\n SELECT c.contact_name INTO v_nome\n FROM public.plg_conversations c\n WHERE c.id = NEW.conversation_id;\n\n PERFORM realtime.send(\n jsonb_build_object(\n 'conversationId', NEW.conversation_id,\n 'channel', NEW.channel,\n 'contactName', coalesce(v_nome, ''),\n -- Um trecho, n\u00E3o o corpo: o suficiente para a notifica\u00E7\u00E3o do sistema\n -- dizer do que se trata sem espalhar a conversa pelo broadcast.\n 'preview', left(coalesce(NEW.body, ''), 120),\n 'at', NEW.at\n ),\n 'inbound',\n 'conversas:' || NEW.tenant_id::text,\n -- Privado: exige que quem assina esteja autenticado. P\u00FAblico deixaria\n -- qualquer um com o nome do t\u00F3pico ouvir a chegada.\n true\n );\n RETURN NEW;\nEND $$;\n\nREVOKE ALL ON FUNCTION public.plg_conversations_anunciar_chegada() FROM public, anon, authenticated;\n\nDROP TRIGGER IF EXISTS plg_conversations_anunciar_chegada ON public.plg_conversation_messages;\nCREATE TRIGGER plg_conversations_anunciar_chegada\n AFTER INSERT ON public.plg_conversation_messages\n FOR EACH ROW EXECUTE FUNCTION public.plg_conversations_anunciar_chegada();\n\nCOMMENT ON FUNCTION public.plg_conversations_anunciar_chegada() IS\n 'Anuncia a chegada no t\u00F3pico `conversas:<tenant>`. Broadcast e n\u00E3o `postgres_changes` porque a RLS da tabela resolve o tenant por cabe\u00E7alho, e o Realtime n\u00E3o manda cabe\u00E7alho (010).';\n";
|
|
12
12
|
export declare const MIGRATION_011_O_ANUNCIO_E_UMA_CAMPAINHA_NAO_UM_RECADO = "-- ---------------------------------------------------------------------------\n-- 011_o_anuncio_e_uma_campainha_nao_um_recado.sql\n--\n-- \u2500\u2500 por que a 010 n\u00E3o podia ficar como estava \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- A 010 anunciava num t\u00F3pico PRIVADO e mandava, no an\u00FAncio, o nome do contato e\n-- um trecho da mensagem. T\u00F3pico privado exige pol\u00EDtica em `realtime.messages` \u2014\n-- e essa tabela \u00E9 do Supabase, dona `supabase_realtime_admin`, um papel que\n-- esta conex\u00E3o n\u00E3o pode assumir:\n--\n-- ERROR: 42501: permission denied to set role \"supabase_realtime_admin\"\n--\n-- Sem a pol\u00EDtica, o servidor recusa a assinatura e nada chega. Com o t\u00F3pico\n-- p\u00FAblico, qualquer um que soubesse o nome do t\u00F3pico leria o trecho da\n-- conversa \u2014 o que n\u00E3o se faz.\n--\n-- \u2500\u2500 a sa\u00EDda: separar o AVISO do CONTE\u00DADO \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- O an\u00FAncio passa a ser uma campainha: diz que chegou algo e em que conversa,\n-- e mais nada. Nome e texto o navegador busca pela via de sempre \u2014 a tabela,\n-- com RLS, onde o cabe\u00E7alho da conta existe e a pol\u00EDtica funciona.\n--\n-- O t\u00F3pico continua carregando o uuid da conta no nome, que \u00E9 o que separa uma\n-- casa da outra. Ele n\u00E3o \u00E9 adivinh\u00E1vel, e mesmo que fosse, o que se ouviria \u00E9\n-- \"chegou mensagem\", sem nome nem texto. O sigilo fica onde sempre esteve: na\n-- leitura da tabela.\n--\n-- \u00C9 uma troca deliberada de superf\u00EDcie: em vez de tentar proteger um caminho\n-- novo, n\u00E3o se p\u00F5e nada sens\u00EDvel nele.\n--\n-- Idempotente e replay-safe.\n-- ---------------------------------------------------------------------------\n\nCREATE OR REPLACE FUNCTION public.plg_conversations_anunciar_chegada()\nRETURNS trigger\nLANGUAGE plpgsql\nSECURITY DEFINER\nSET search_path = ''\nAS $$\nBEGIN\n -- S\u00F3 o que CHEGA. A resposta que o operador manda tamb\u00E9m \u00E9 um INSERT, e\n -- anunci\u00E1-la faria o sistema apitar para quem acabou de digitar.\n IF NEW.direction IS DISTINCT FROM 'inbound' THEN\n RETURN NEW;\n END IF;\n\n PERFORM realtime.send(\n -- S\u00D3 o id da conversa. Nem nome, nem trecho, nem corpo: quem ouve vai\n -- buscar isso na tabela, com a pol\u00EDtica de leitura no meio do caminho.\n -- Um uuid sozinho n\u00E3o conta nada a quem n\u00E3o pode ler a conversa.\n jsonb_build_object('conversationId', NEW.conversation_id),\n 'inbound',\n 'conversas:' || NEW.tenant_id::text,\n -- P\u00DABLICO, e por isso o payload \u00E9 vazio de conte\u00FAdo. Privado exigiria uma\n -- pol\u00EDtica numa tabela que n\u00E3o \u00E9 nossa.\n false\n );\n RETURN NEW;\nEND $$;\n\nCOMMENT ON FUNCTION public.plg_conversations_anunciar_chegada() IS\n 'Toca a campainha no t\u00F3pico `conversas:<tenant>` \u2014 s\u00F3 o id da conversa. O conte\u00FAdo \u00E9 lido da tabela, com RLS (011).';\n";
|
|
13
|
+
export declare const MIGRATION_012_A_RICH_MESSAGE_KEEPS_ITS_SHAPE = "-- ---------------------------------------------------------------------------\n-- 012_a_rich_message_keeps_its_shape.sql\n--\n-- \u2500\u2500 what was lost, and how \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- `plg_conversation_messages` has exactly one content column: `body text`. A\n-- WhatsApp message that is not text therefore arrives flattened to whatever\n-- string the ingest could make of it \u2014 and when the ingest could make none, to\n-- the empty string, which renders as an empty bubble.\n--\n-- On 2026-09-22 a lead sent his finance director's contact card. It stored as\n-- `body = ''`. He then sent a screenshot of the same card; that stored as\n-- `body = ''` too. The fact the conversation existed to obtain \u2014 a name and a\n-- phone number \u2014 was in the payload both times and in the row neither time.\n--\n-- Recovering it meant going back to the Evolution instance and reading the\n-- provider's own copy. That worked, but it is not a recovery path: Evolution\n-- prunes, the instance is local-only, and a row that needs a second system to\n-- be legible is not a record.\n--\n-- \u2500\u2500 the two columns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- `message_type` names what the provider sent \u2014 text, contact, image, audio,\n-- document, sticker, location, reaction, unknown. The inbox needs it to choose\n-- a bubble, and `unknown` is the one that makes the NEXT gap visible in a query\n-- instead of in a complaint.\n--\n-- `payload` keeps the part that does not survive flattening: the vCard's parsed\n-- name and numbers, a media mimetype and size, a location's coordinates. Not\n-- the whole provider envelope \u2014 that carries decryption keys and a base64\n-- thumbnail, neither of which belongs in a row that every member of the tenant\n-- can read.\n--\n-- Deliberately NOT stored here: delivery status. It changes after the fact \u2014\n-- sent, delivered, read \u2014 and `conversations-provider`'s `message_detail` reads\n-- it live for that reason. `payload` is the shape of the message, which does\n-- not change once it arrives.\n--\n-- \u2500\u2500 why both are nullable, and nothing is backfilled \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- Every row written before this migration has neither, and no default can\n-- invent them: `message_type` would have to guess, and guessing 'text' for the\n-- three empty bubbles already in the table would assert something false about\n-- exactly the rows this exists to fix. A reader that treats NULL as \"written\n-- before 012\" is correct; a reader that treats '' as text is the bug.\n--\n-- Table-level `GRANT ALL ... TO authenticated` already covers new columns, and\n-- the four tenant policies are row-scoped, so neither needs restating.\n--\n-- Idempotent and replay-safe.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_conversation_messages\n ADD COLUMN IF NOT EXISTS message_type text,\n ADD COLUMN IF NOT EXISTS payload jsonb;\n\nCOMMENT ON COLUMN public.plg_conversation_messages.message_type IS\n 'What the provider sent: text, contact, image, video, audio, document, sticker, location, reaction, unknown. NULL means the row predates 012 (#504).';\n\nCOMMENT ON COLUMN public.plg_conversation_messages.payload IS\n 'The structured remainder that `body` cannot hold \u2014 parsed vCards, media metadata, coordinates. Never credentials, thumbnails or decryption keys; never delivery status, which is read live (#504).';\n";
|
|
14
|
+
export declare const MIGRATION_013_A_MIDIA_FICA_CONOSCO = "-- ---------------------------------------------------------------------------\n-- 013_a_midia_fica_conosco.sql\n--\n-- \u2500\u2500 o que a 012 resolveu, e o que ela n\u00E3o resolveu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- A 012 fez a mensagem que n\u00E3o \u00E9 texto parar de chegar como bolha vazia:\n-- `message_type` diz que \u00E9 imagem, `payload` guarda mimetype, tamanho e\n-- dura\u00E7\u00E3o. Funcionou \u2014 um \u00E1udio de 23 segundos entrou classificado como\n-- `audio`, `ptt: true`, `audio/ogg; codecs=opus`, 55.825 bytes.\n--\n-- E a tela mostra `[\u00E1udio]`. Porque saber QUE existe um arquivo n\u00E3o \u00E9 ter o\n-- arquivo. Nada no banco aponta para bytes nenhuns: o WhatsApp entrega m\u00EDdia\n-- cifrada num CDN pr\u00F3prio, e quem decifra \u00E9 o provedor.\n--\n-- \u2500\u2500 por que uma coluna, e n\u00E3o um campo no payload \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- A 012 escreveu que `payload` \u00E9 \"a forma da mensagem, que n\u00E3o muda depois que\n-- ela chega\". Onde o arquivo foi parar \u00E9 decidido DEPOIS \u2014 no upload, que pode\n-- falhar, ser refeito, ou ainda n\u00E3o ter acontecido. Enfiar isso no `payload`\n-- contradiz a \u00FAnica frase que diz quando `payload` pode ser lido sem medo.\n--\n-- Em coluna, a pergunta que importa vira consulta:\n--\n-- SELECT count(*) FROM plg_conversation_messages\n-- WHERE message_type IN ('image','video','audio','document','sticker')\n-- AND media_path IS NULL;\n--\n-- \"quanta m\u00EDdia eu recebi e n\u00E3o guardei\" \u2014 que num campo de JSON seria uma\n-- varredura e aqui \u00E9 um \u00EDndice.\n--\n-- \u2500\u2500 por que guardar, em vez de buscar no provedor quando algu\u00E9m abrir \u2500\u2500\u2500\n--\n-- A Evolution decifra sob demanda, e seria mais barato n\u00E3o copiar nada. Mas ela\n-- \u00E9 local-only, poda o que \u00E9 antigo, e a inst\u00E2ncia roda numa m\u00E1quina que nem\n-- sempre est\u00E1 de p\u00E9. Essa era exatamente a obje\u00E7\u00E3o da 012 contra depender dela\n-- para ler um vCard: uma linha que precisa de um segundo sistema para ser\n-- leg\u00EDvel n\u00E3o \u00E9 registro. Vale igual para os bytes.\n--\n-- O destino \u00E9 o balde `attachments` \u2014 privado, 25 MB, j\u00E1 existente e j\u00E1 em uso.\n-- Uma foto que um lead mandou no WhatsApp n\u00E3o pode ser p\u00FAblica, e um balde novo\n-- seria mais uma lista de mimetypes para algu\u00E9m manter desatualizada.\n--\n-- \u2500\u2500 nulo \u00E9 um estado leg\u00EDtimo, n\u00E3o uma falha \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n--\n-- `media_path` \u00E9 NULL em tr\u00EAs situa\u00E7\u00F5es diferentes e todas normais: a mensagem\n-- \u00E9 texto; a linha \u00E9 anterior a esta migra\u00E7\u00E3o; ou o upload ainda n\u00E3o aconteceu.\n-- Quem l\u00EA distingue pela combina\u00E7\u00E3o com `message_type`, que \u00E9 o que torna a\n-- consulta acima poss\u00EDvel. Um default inventaria um caminho para arquivo que\n-- n\u00E3o existe.\n--\n-- Idempotente e replay-safe.\n-- ---------------------------------------------------------------------------\n\nALTER TABLE public.plg_conversation_messages\n ADD COLUMN IF NOT EXISTS media_path text;\n\nCOMMENT ON COLUMN public.plg_conversation_messages.media_path IS\n 'Onde os bytes ficaram no balde `attachments`, ou NULL: texto, linha anterior \u00E0 013, ou upload que ainda n\u00E3o aconteceu. Distingue-se pela combina\u00E7\u00E3o com `message_type` (013).';\n\n-- Parcial: s\u00F3 a m\u00EDdia sem arquivo interessa, e \u00E9 a minoria. O \u00EDndice fica do\n-- tamanho do problema em vez do tamanho da tabela.\nCREATE INDEX IF NOT EXISTS plg_conversation_messages_midia_sem_arquivo\n ON public.plg_conversation_messages (tenant_id, at DESC)\n WHERE media_path IS NULL\n AND message_type IN ('image', 'video', 'audio', 'document', 'sticker');\n";
|
|
13
15
|
export declare const MIGRATIONS: Array<{
|
|
14
16
|
id: string;
|
|
15
17
|
sql: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,2rhCAkgBlC,CAAA;AAED,eAAO,MAAM,gDAAgD,i0LAuG5D,CAAA;AAED,eAAO,MAAM,oDAAoD,m5bAuOhE,CAAA;AAED,eAAO,MAAM,0DAA0D,81rBAwWtE,CAAA;AAED,eAAO,MAAM,gEAAgE,+lJA2E5E,CAAA;AAED,eAAO,MAAM,yDAAyD,w1RAmKrE,CAAA;AAED,eAAO,MAAM,sCAAsC,mtOA6HlD,CAAA;AAED,eAAO,MAAM,6CAA6C,qmIA6DzD,CAAA;AAED,eAAO,MAAM,yCAAyC,ywGA8CrD,CAAA;AAED,eAAO,MAAM,qDAAqD,40FAiDjE,CAAA;AAED,eAAO,MAAM,6CAA6C,6oJA0FzD,CAAA;AAED,eAAO,MAAM,qDAAqD,itGA8DjE,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,2rhCAkgBlC,CAAA;AAED,eAAO,MAAM,gDAAgD,i0LAuG5D,CAAA;AAED,eAAO,MAAM,oDAAoD,m5bAuOhE,CAAA;AAED,eAAO,MAAM,0DAA0D,81rBAwWtE,CAAA;AAED,eAAO,MAAM,gEAAgE,+lJA2E5E,CAAA;AAED,eAAO,MAAM,yDAAyD,w1RAmKrE,CAAA;AAED,eAAO,MAAM,sCAAsC,mtOA6HlD,CAAA;AAED,eAAO,MAAM,6CAA6C,qmIA6DzD,CAAA;AAED,eAAO,MAAM,yCAAyC,ywGA8CrD,CAAA;AAED,eAAO,MAAM,qDAAqD,40FAiDjE,CAAA;AAED,eAAO,MAAM,6CAA6C,6oJA0FzD,CAAA;AAED,eAAO,MAAM,qDAAqD,itGA8DjE,CAAA;AAED,eAAO,MAAM,4CAA4C,6gIA6DxD,CAAA;AAED,eAAO,MAAM,kCAAkC,qlIAiE9C,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAezD,CAAA"}
|
package/dist/types.d.ts
CHANGED
|
@@ -62,6 +62,51 @@ export interface Message {
|
|
|
62
62
|
deliveryStatus?: string | null;
|
|
63
63
|
/** O id no provedor. Sem ele, não saiu — e é a chave para buscar o JSON cru. */
|
|
64
64
|
providerMessageId?: string | null;
|
|
65
|
+
/**
|
|
66
|
+
* What the provider sent, when it was not plain text. Absent on every row
|
|
67
|
+
* written before migration 012 — absent is "unknown", never "text", because
|
|
68
|
+
* the rows this exists for are exactly the ones that stored as empty text.
|
|
69
|
+
*/
|
|
70
|
+
messageType?: MessageType | null;
|
|
71
|
+
/**
|
|
72
|
+
* The part `body` cannot hold: parsed vCards, media metadata, coordinates.
|
|
73
|
+
* Shape follows `messageType`; see functions/_shared/evolution-runtime.js.
|
|
74
|
+
*/
|
|
75
|
+
payload?: MessagePayload | null;
|
|
76
|
+
/**
|
|
77
|
+
* Where the bytes are, in the private `attachments` bucket — or null, which
|
|
78
|
+
* means one of three ordinary things: the message is text, the row predates
|
|
79
|
+
* 013, or the upload did not happen. Never a URL: the bucket is private and
|
|
80
|
+
* a link has to be signed per view, which `media_url` does against the row
|
|
81
|
+
* rather than against a path the client supplies.
|
|
82
|
+
*/
|
|
83
|
+
mediaPath?: string | null;
|
|
84
|
+
}
|
|
85
|
+
export type MessageType = 'text' | 'contact' | 'image' | 'video' | 'audio' | 'document' | 'sticker' | 'location' | 'reaction' | 'unknown';
|
|
86
|
+
/** A contact card someone forwarded into the thread. The number in it is
|
|
87
|
+
* routinely the reason the conversation is happening. */
|
|
88
|
+
export interface SharedContact {
|
|
89
|
+
name: string;
|
|
90
|
+
/** `display` is what a human reads back; `digits` is what dials. */
|
|
91
|
+
phones: Array<{
|
|
92
|
+
display: string;
|
|
93
|
+
digits: string;
|
|
94
|
+
}>;
|
|
95
|
+
}
|
|
96
|
+
export interface MessagePayload {
|
|
97
|
+
contacts?: SharedContact[];
|
|
98
|
+
mimetype?: string | null;
|
|
99
|
+
fileName?: string | null;
|
|
100
|
+
fileLength?: number | null;
|
|
101
|
+
seconds?: number | null;
|
|
102
|
+
ptt?: boolean | null;
|
|
103
|
+
caption?: string | null;
|
|
104
|
+
latitude?: number | null;
|
|
105
|
+
longitude?: number | null;
|
|
106
|
+
name?: string | null;
|
|
107
|
+
address?: string | null;
|
|
108
|
+
/** Only on `unknown`: the provider keys nobody has mapped yet. */
|
|
109
|
+
keys?: string[];
|
|
65
110
|
}
|
|
66
111
|
export interface ListConversationsQuery {
|
|
67
112
|
channel?: Channel | 'all';
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,CAAA;AAE5E,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE9D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,CAAA;AAErD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;;;;;;;OAWG;IACH,oBAAoB,CAAC,EAAE,gBAAgB,CAAA;IACvC,WAAW,EAAE,MAAM,CAAA;IACnB;;;8EAG0E;IAC1E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,MAAM,EAAE,kBAAkB,CAAA;IAC1B,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;gFAE4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,CAAA;IAEd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,gBAAgB,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd;;6EAEyE;IACzE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,gFAAgF;IAChF,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Message } from '../types';
|
|
3
|
+
export declare function temArquivo(m: Message): boolean;
|
|
4
|
+
export declare function MediaBubble({ m, outbound }: {
|
|
5
|
+
m: Message;
|
|
6
|
+
outbound: boolean;
|
|
7
|
+
}): React.JSX.Element;
|
|
8
|
+
//# sourceMappingURL=MediaBubble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaBubble.d.ts","sourceRoot":"","sources":["../../src/views/MediaBubble.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAMvC,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAE9C;AAkDD,wBAAgB,WAAW,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,qBAyG7E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageThread.d.ts","sourceRoot":"","sources":["../../src/views/MessageThread.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"MessageThread.d.ts","sourceRoot":"","sources":["../../src/views/MessageThread.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,OAAO,KAAK,EAAE,YAAY,EAA0B,MAAM,UAAU,CAAA;AAkGpE,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;IACvF,QAAQ,EAAE,YAAY,CAAA;IACtB,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,qBA0KA"}
|