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

@zevanoo/baileys-ez

v1.1.1

Published

Custom Baileys wrapper for multi-device WhatsApp bot

Readme

Baileys-ez

A powerful and easy-to-use wrapper for the Baileys WhatsApp Web API library. This wrapper simplifies multi-device bot management, enhances interactive message capabilities, and streamlines session handling.

Features

  • Multi-Client Management: Easily manage multiple WhatsApp accounts using a single Wrapper instance created with createWrapper.
  • Simplified Event Handling: Unified event system for both single and multi-client setups with simplified event names (e.g., contact.add, message.remove).
  • Enhanced Interactive Messages: Send rich interactive buttons (Quick Replies, CTAs, Single Select, etc.)
  • Automatic Session Management: Connect, validate, clean, and remove sessions automatically or manually via the createWrapper.
  • Direct Baileys Access: Access all original Baileys functions via client.sock for advanced use cases.
  • Action Helpers: Convenient methods like sendButtons, sendInteractiveMessage, sendContact, react, etc., are bound to the client.sock instance.
  • Re-exports Baileys: All functions, types, and objects from baileys are available directly from this package.

Installation

  • Using npm:

    npm install @zevanoo/baileys-ez
  • Using yarn:

    yarn add @zevanoo/baileys-ez

Usage

Connection

import { Client, Browsers } from '@zevanoo/baileys-ez';

const socket = new Client({
    id: 'my_bot',
    number: '6281234567890', // WhatsApp number
    baileysConfig: {
      browser: Browsers.ubuntu('Chrome')
      // other baileys config
    },
    pairingCode: '12345678' // must 8 char, no more or less, optional
    serializer: (client, m) => {
      return m
    }
});

socket.on('connection', (data) => {
    console.log('Connection status:', data.status);
    
    if (data.status === 'connecting') {
      console.log('Connecting to number')
    }
    
    if (data.status === 'pairing-code') {
      console.log(data.code)
    }
    
    if (data.status === 'open') {
      console.log('Connection open')
    }
    
    if (data.status === 'close') {
      console.log(data.statusCode)
      console.log(data.reason)
    }
});

await socket.connect();
// await socket.disconnect(); // disconnect connection

Multi-Client with Wrapper

import { createWrapper, Client, Browsers } from '@zevanoo/baileys-ez';

const wrapper = createWrapper({
    folderName: 'sessions', // Folder to store session data
    serializer: (client, m) => {
      return m
    },
    pairingCode: '12345678' // same pairing code for all number
    baileysConfig: {
      browser: Browsers.ubuntu('Chrome'),
      // other baileys config
    }
});

const socket = new Client({ id: 'bot1', number: '6281234567890' });
const socket1 = new Client({ id: 'bot2', number: '6281234567891' });

wrapper.on('message.new', (message) => {
    console.log(`Message from ${message.clientId}:`, message.data.text);
});

wrapper.on('connection', (data) => {
    if (data.data.status === 'connecting') {
      console.log(`id ${data.clientId} is connecting`)
    }
    
    if (data.data.status === 'pairing-code') {
      console.log(`pairing code for id ${data.clientId}: ${data.data.code}`)
    }
    
    if (data.data.status === 'open') {
      console.log('Connection open for id: ', data.clientId)
    }
    
    if (data.data.status === 'close') {
      console.log(`Connection closed for id ${data.clientId}: ${data.data.statusCode} ${data.data.reason}`)
    }
});

await wrapper.connectAll();

Note: option serializer have default function, you can set custom if you don't want use this message metadata

Connection Management (via Wrapper)

The Wrapper provides methods for managing connection of its managed clients.

import { createWrapper, Client } from '@zevanoo/baileys-ez';

const wrapper = createWrapper({
    folderName: 'sessions',
});

const socket = new Client({ id: 'bot1', number: '6281234567890' });

// connect all number
await wrapper.connectAll();

// get instance client
const client = await wrapper.getClient('bot1');

// get all instance client
const info = await wrapper.getAllClients();

// disconnect all number
await wrapper.disconnectAll();

// await wrapper.removeClient('bot1'); // remove from list and disconnect

Session Management (via Wrapper)

The Wrapper provides methods for managing sessions of its managed clients.

import { createWrapper, Client } from '@zevanoo/baileys-ez';

const wrapper = createWrapper({
    folderName: 'sessions',
});

const socket = new Client({ id: 'bot1', number: '6281234567890' });

await wrapper.cleanupCorruptSessions();

const sessions = await wrapper.listValidSessions();
console.log('Valid sessions in base folder:', sessions);

const info = await wrapper.getSessionInfo('bot1');
console.log('Session info for bot1 (from base):', info);

await wrapper.connectAll();
const clientSessionInfo = await wrapper.checkAllClientSessions();
console.log('Client session statuses:', clientSessionInfo);

await wrapper.cleanClientSessions();

// await wrapper.removeSession('bot_to_remove');

Handling Events

Generic Events

socket.on('connection', ctx => console.log(ctx));
socket.on('error', ctx => console.log(ctx));
socket.on('chat', ctx => console.log(ctx));
socket.on('contact', ctx => console.log(ctx));
socket.on('group', ctx => console.log(ctx));
socket.on('message', ctx => console.log(ctx));
socket.on('call', ctx => console.log(ctx));
socket.on('presence.update', ctx => console.log(ctx));
socket.on('blocklist', ctx => console.log(ctx));
socket.on('label', ctx => console.log(ctx));
socket.on('newsletter', ctx => console.log(ctx));
socket.on('session.removed', ctx => console.log(ctx));

Specific Events

socket.on('chat.add', ctx => console.log(ctx));
socket.on('chat.update', ctx => console.log(ctx));
socket.on('chat.remove', ctx => console.log(ctx));
socket.on('history.set', ctx => console.log(ctx));

socket.on('contact.add', ctx => console.log(ctx));
socket.on('contact.update', ctx => console.log(ctx));

socket.on('group.add', ctx => console.log(ctx));
socket.on('group.update', ctx => console.log(ctx));
socket.on('group.member.add', ctx => console.log(ctx));
socket.on('group.member.remove', ctx => console.log(ctx));
socket.on('group.member.promote', ctx => console.log(ctx));
socket.on('group.member.demote', ctx => console.log(ctx));
socket.on('group.request.join', ctx => console.log(ctx));

socket.on('message.new', ctx => console.log(ctx));
socket.on('message.update', ctx => console.log(ctx));
socket.on('message.remove', ctx => console.log(ctx));
socket.on('message.receipt', ctx => console.log(ctx));
socket.on('message.react', ctx => console.log(ctx));
socket.on('message.media.update', ctx => console.log(ctx));

socket.on('blocklist.set', ctx => console.log(ctx));
socket.on('blocklist.add', ctx => console.log(ctx));
socket.on('blocklist.remove', ctx => console.log(ctx));

socket.on('label.edit', ctx => console.log(ctx));
socket.on('label.association.add', ctx => console.log(ctx));
socket.on('label.association.remove', ctx => console.log(ctx));

socket.on('newsletter.reaction', ctx => console.log(ctx));
socket.on('newsletter.view', ctx => console.log(ctx));
socket.on('newsletter-participants.update', ctx => console.log(ctx));
socket.on('newsletter-settings.update', ctx => console.log(ctx));

Note: All events also added to wrapper.on()

Messages Function

 const client = socket.sock;
 
 await client.sendText(jid, 'Example', options);
 
 await client.react(jid, m.key, '🗿');
 
 await client.sendContact(jid, [{
   name: 'zevanoo',
   number: '12345678',
   about: 'About'
 }], options);
 
 await client.downloadMediaMessage(m);
 
 client.parseMention(m);
 
 client.decodeJid(jid);
 
 // buttons
 await client.sendButtons(jid, {
     text: 'Pick one',
     buttons: [
         { id: 'yes', text: 'Yes' },
         { id: 'no', text: 'No' }
     ]
 });
 
 // media
 await client.sendMedia(jid, 'https://telegra.ph/file/906c47ef4ab5bb9ccbe48.jpg', m, { mimetype: 'image/png' });
 await client.sendMedia(jid, 'https://telegra.ph/file/906c47ef4ab5bb9ccbe48.jpg', m, { mimetype: 'image/png', asDocument: true });
 
 // interactive message
 await client.sendInteractiveMessage(jid, {
   text: 'Contact actions',
   footer: 'Footer',
   interactiveButtons: [
     { name: 'cta_url', buttonParamsJson: JSON.stringify({ display_text: 'Docs', url: 'https://example.com' }) },
     { name: 'cta_copy', buttonParamsJson: JSON.stringify({ display_text: 'Copy Code', copy_code: 'ABC-123' }) },
     { name: 'cta_call', buttonParamsJson: JSON.stringify({ display_text: 'Call Support', phone_number: '+1234567890' }) },
     { name: 'send_location', buttonParamsJson: JSON.stringify({ display_text: 'Share Location' }) },
     { name: 'quick_reply', buttonParamsJson: JSON.stringify({ display_text: 'Hello', id: 'hi' }) },
         { name: 'single_select', buttonParamsJson: JSON.stringify({
             title: 'Menu',
             sections: [{
                 title: 'Options',
                 rows: [
                     { id: 'opt1', title: 'Option 1', description: 'Desc 1' },
                     { id: 'opt2', title: 'Option 2', description: 'Desc 2' }
                 ]
             }]
         })}
   ]
 });

Accessing Original Baileys Functions

All exports from baileys are available from this package.

import { DisconnectReason, Client } from '@zevanoo/baileys-ez';

const singleClient = new Client({...});
await singleClient.sock.sendMessage(...);

Message Metadata

{
  "raw": {
    "key": {
      "remoteJid": "[email protected]",
      "remoteJidAlt": "lid@lid",
      "fromMe": false,
      "id": "unique",
      "participant": "",
      "addressingMode": "pn"
    },
    "messageTimestamp": number,
    "pushName": "name",
    "broadcast": false,
    "message": {
      "extendedTextMessage": {
        "text": ".testt a --p a --t",
        "previewType": "NONE",
        "contextInfo": {
          "expiration": 0,
          "ephemeralSettingTimestamp": "number",
          "disappearingMode": {
            "initiator": "CHANGED_IN_CHAT",
            "trigger": "UNKNOWN"
          }
        },
        "inviteLinkGroupTypeV2": "DEFAULT"
      },
      "messageContextInfo": {
        "deviceListMetadata": {
          "senderKeyHash": "unique",
          "senderTimestamp": "number",
          "recipientKeyHash": "unique",
          "recipientTimestamp": "number"
        },
        "deviceListMetadataVersion": number,
        "messageSecret": "unique"
      }
    }
  },
  "key": {
    "remoteJid": "[email protected]",
    "remoteJidAlt": "lid@lid",
    "fromMe": false,
    "id": "unique",
    "participant": "",
    "addressingMode": "pn"
  },
  "message": {
    "extendedTextMessage": {
      "text": ".testt a --p a --t",
      "previewType": "NONE",
      "contextInfo": {
        "expiration": 0,
        "ephemeralSettingTimestamp": "number",
        "disappearingMode": {
          "initiator": "CHANGED_IN_CHAT",
          "trigger": "UNKNOWN"
        }
      },
      "inviteLinkGroupTypeV2": "DEFAULT"
    },
    "messageContextInfo": {
      "deviceListMetadata": {
        "senderKeyHash": "unique",
        "senderTimestamp": "number",
        "recipientKeyHash": "unique",
        "recipientTimestamp": "number"
      },
      "deviceListMetadataVersion": number,
      "messageSecret": "unique"
    }
  },
  "from": "[email protected]",
  "fromMe": false,
  "id": "unique",
  "device": "android",
  "isBaileys": false,
  "isGroup": false,
  "participant": null,
  "sender": "[email protected]",
  "pushName": "name",
  "type": "extendedTextMessage",
  "msg": {
    "text": ".testt a --p a --t",
    "previewType": "NONE",
    "contextInfo": {
      "expiration": 0,
      "ephemeralSettingTimestamp": "number",
      "disappearingMode": {
        "initiator": "CHANGED_IN_CHAT",
        "trigger": "UNKNOWN"
      }
    },
    "inviteLinkGroupTypeV2": "DEFAULT"
  },
  "mentions": [],
  "expiration": 0,
  "isQuoted": false,
  "isMedia": false,
  "body": ".testt a --p a --t",
  "prefix": ".",
  "prefixes": [
    ".",
    "!",
    "#",
    "/"
  ],
  "command": "testt",
  "args": [
    "a",
    "--p",
    "a",
    "--t"
  ],
  "text": "a --p a --t",
  "argsParsed": {
    "p": "a",
    "t": true
  },
  "timestamp": number,
  "quoted": null
}