@markedesk/plugin-sdk
v0.1.0
Published
SDK para criar plugins do Markedesk — interfaces, tipos e helpers
Maintainers
Readme
@markedesk/plugin-sdk
SDK oficial pra construir plugins remotos do Markedesk-NG.
Plugins são processos externos (HTTP) que estendem o Markedesk com:
- Canais de comunicação próprios (WhatsApp, Telegram, etc)
- Reação a eventos do sistema (mensagem chegou, ticket fechou, contato atualizado…)
- Ações custom na UI (botões em ticket/contact/dashboard)
- Painéis custom (iframes em slots da UI)
- Settings declarativos com tabs, lista, condicionais, componentes visuais ricos
- Páginas HTML próprias renderizadas em iframe (qualquer stack, liberdade total)
- Storage persistente (KV) com cache Redis e rate limit, escopado por plugin × empresa
- Hot-reload via UI: atualiza metadata e hooks sem reiniciar backend
O SDK cuida de toda a infraestrutura: servidor Express, WebSocket, autenticação, auto-provisioning, persistência. Você escreve só lógica de negócio.
Quickstart
mkdir meu-plugin && cd meu-plugin
bun init -y
bun add @markedesk/plugin-sdk express wsindex.ts:
import { definePlugin, PluginServer } from "@markedesk/plugin-sdk";
const server = new PluginServer({
metadata: definePlugin({
id: "meu-plugin",
displayName: "Meu Plugin",
color: "#7c4dff",
icon: "Build",
version: "1.0.0",
provides: {
hooks: [
{ event: "message:received", endpoint: "/hook" }
]
}
}),
async onHook(event, data) {
if (event === "message:received") {
console.log(`[${data.companyId}] cliente disse: ${data.message.body}`);
await server.client?.sendText({
ticketId: data.ticket.id,
body: "Recebi sua mensagem!"
});
}
}
});
server.start();bun run index.tsPlugin sobe em http://localhost:3033. Sem nenhuma chave em variável de ambiente.
Cadastre no Markedesk → admin gera key, envia pro plugin via POST /admin/provision, plugin salva e fica ativo. Cliente envia mensagem → plugin recebe message:received → responde.
Documentação
Cada tema em arquivo próprio:
| Doc | Conteúdo |
|---|---|
| provisioning.md | Auto-provisioning, callbacks, persistência, env vars |
| events.md | Eventos: hooks do backend (payloads tipados, intercept), eventos de canal (emit/on tipados, constantes CHANNEL_*) e ciclo de vida do plugin (PLUGIN_*) |
| client.md | MarkedeskClient + PluginStorage + endpoints /plugin-api/* |
| ui.md | Settings declarativos: inputs, containers, display, ações |
| slots.md | Slots & pipelines de UI: PluginBridge, render html/route, intercept, hooks de decisão, priority, slots de wrap (PluginWrap/registerSlot) |
| runtime.md | PluginRuntime: contexto da sessão (usuário, config, conexões+mensagens custom, settings da empresa, ticket aberto), eventos (on/onTicketMessage), ações (actions/registerActions), debug. Nota de segurança: reflete o que o backend já autorizou |
| routes.md | Rotas custom, actions na UI, painéis, webhooks |
| channels.md | Plugin como provedor de canal (WhatsApp, Telegram, etc.) |
| types.md | DTOs: Contact, Ticket, Message, Connection, User, Queue, Tag |
| troubleshooting.md | Erros comuns, debug, recovery |
| examples.md | 13 exemplos prontos pra copiar |
| plugin-proxy | Multi-empresa: servir N empresas com 1 plugin atrás de 1 endereço (proxy reverso roteia por path, sobe instância sob demanda). O SDK não muda — cada empresa é um processo single-tenant. |
API Reference (rápido)
Exports principais
// Helpers
import { definePlugin } from "@markedesk/plugin-sdk";
// Classes
import { PluginServer, MarkedeskClient } from "@markedesk/plugin-sdk";
// Tipos de evento
import type {
TypedHookHandler,
HookEventName,
PayloadOf,
IHookEventPayloads
} from "@markedesk/plugin-sdk";
// DTOs
import type {
ContactDTO,
TicketDTO,
MessageDTO,
ConnectionDTO,
UserDTO,
QueueDTO,
TagDTO
} from "@markedesk/plugin-sdk";new PluginServer(options)
{
metadata: IPluginMetadata,
port?: number, // default: env PORT || 3033
apiKey?: string, // default: env API_KEY (legado)
configFile?: string, // default: ./data/plugin-config.json
channel?: ChannelHandlers, // @deprecated — prefira server.on(CHANNEL_*, fn)
onHook?: TypedHookHandler, // se provides.hooks
routes?: (router) => void, // se provides.routes
markedeskUrl?: string, // default: env MARKEDESK_URL
markedeskApiKey?: string, // default: env MARKEDESK_API_KEY ou auto-provision
heartbeatMs?: number, // intervalo do heartbeat WS
ackTimeoutMs?: number, // timeout do ACK de entrega garantida
onProvisioned?: ({ companyId, markedeskUrl, client }) => Promise<void>, // @deprecated — use on(PLUGIN_PROVISIONED)
onDeprovisioned?: ({ companyId }) => Promise<void> // @deprecated — use on(PLUGIN_DEPROVISIONED)
}Atributos do server
server.client: MarkedeskClient | null— cliente HTTP autenticado, disponível após provisionamentoserver.metadata: IPluginMetadata— metadata declarada (comsdkVersion, capabilities/routes/hooks derivados)server.app: Express— instância Express (pra middleware custom)server.start()/server.stop()— sobe/derruba HTTP+WSserver.on(CHANNEL_SEND_TEXT, fn)— registra operação de canal (backend → plugin), tipada porChannelRequestMapserver.on(PLUGIN_STARTED, fn)— registra evento de ciclo de vida, tipado porPluginEventMapserver.emit(event, data)— emite evento de canal (plugin → backend), tipado porChannelEventMap;server.emitRaw(name, data)para eventos customserver.emitMessage(connectionId, msg)/server.emitStatus(connectionId, { status, qrcode?, error? })— helpers de canalserver.emitAck/emitCall/emitPresence/emitImport/emitImportProgress/emitInitProgress— demais emitters de canal
Convenções
- Single-tenant: 1 plugin = 1 empresa. Backend rejeita registrar a mesma URL pra duas empresas
- Idempotência:
upsertAgent,storage.set, registro de plugin — chamar várias vezes sem efeito colateral - Fail-soft: erro no plugin não derruba o backend. Erro no backend não derruba o plugin
- Sem retry built-in: se o plugin estiver offline durante um evento, o evento é perdido. Use
PluginStoragepra reconciliar estado em recovery (ver examples.md)
Fluxo end-to-end
1. Plugin sobe sem credencial → modo "não-provisionado"
│
▼
2. Empresa cadastra no Markedesk → POST /plugins/remote { baseUrl }
│ backend gera apiKey
│ POSTa /admin/provision
▼
3. Plugin recebe → salva ./data/plugin-config.json
chama onProvisioned()
│
▼
4. Empresa cliente fala → Markedesk dispara message:received
(WS preferencial, HTTP fallback)
│
▼
5. Plugin reage no onHook → server.client.sendText(...)
(com X-Plugin-Api-Key)
│
▼
6. Backend valida e envia → via canal nativo ou outro pluginVeja também
plugins/plugin-agent— exemplo completo de plugin de IA com agente autônomo, hooks tipados, storage, MarkedeskClientplugins/plugin-baileys— plugin de canal (WhatsApp via Baileys)plugins/plugin-wwebjs— plugin de canal (WhatsApp via whatsapp-web.js)plugins/plugin-proxy— proxy reverso pra servir o mesmo plugin a N empresas (1 endereço, roteia por path, sobe instância sob demanda)
Comece em docs/provisioning.md ou pule pro examples.md se quer ver código.
