npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@markedesk/plugin-sdk

v0.1.0

Published

SDK para criar plugins do Markedesk — interfaces, tipos e helpers

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 ws

index.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.ts

Plugin 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 provisionamento
  • server.metadata: IPluginMetadata — metadata declarada (com sdkVersion, capabilities/routes/hooks derivados)
  • server.app: Express — instância Express (pra middleware custom)
  • server.start() / server.stop() — sobe/derruba HTTP+WS
  • server.on(CHANNEL_SEND_TEXT, fn) — registra operação de canal (backend → plugin), tipada por ChannelRequestMap
  • server.on(PLUGIN_STARTED, fn) — registra evento de ciclo de vida, tipado por PluginEventMap
  • server.emit(event, data) — emite evento de canal (plugin → backend), tipado por ChannelEventMap; server.emitRaw(name, data) para eventos custom
  • server.emitMessage(connectionId, msg) / server.emitStatus(connectionId, { status, qrcode?, error? }) — helpers de canal
  • server.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 PluginStorage pra 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 plugin

Veja também

  • plugins/plugin-agent — exemplo completo de plugin de IA com agente autônomo, hooks tipados, storage, MarkedeskClient
  • plugins/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.