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

@jdic/jcore

v0.2.0

Published

> A lightweight, modular TypeScript framework for building WhatsApp bots with [whatsapp-web.js](https://wwebjs.dev/).

Readme

@jdic/jcore

A lightweight, modular TypeScript framework for building WhatsApp bots with whatsapp-web.js.

TypeScript Bun

✨ Features

  • 🎯 Command System - Dynamic command loading with aliases, categories, and cooldowns
  • Event Handler - Modular event management for all WhatsApp events
  • 🛠️ Builder Pattern - Clean, fluent API for creating commands and events
  • 📦 Collection Utilities - Enhanced Map with powerful utility methods
  • 🔒 Permission System - Built-in owner-only and group-only command restrictions
  • ⏱️ Cooldown Management - Automatic cooldown tracking and cleanup
  • 🧪 Type-Safe - Full TypeScript support with comprehensive type definitions
  • 🚀 Fast Runtime - Powered by Bun for blazing-fast performance
  • 📝 Well-Tested - Includes test suite with Bun's test runner

📦 Installation (as Package)

npm install @jdic/jcore

📦 Installation (Full)

Prerequisites

  • Bun
  • A WhatsApp account for bot authentication

Quick Start

# Clone the repository
git clone https://github.com/jdic/jcore.git
cd jcore

# Install dependencies
bun install

# Configure environment variables
cp .env.sample .env
# Edit .env with your bot configuration

# Run the bot
bun start

Environment Configuration

Create a .env file in the project root:

# Command prefix (e.g., !, >, ., /)
BOT_PREFIX=!

# Bot owner's WhatsApp number (digits only or with @c.us suffix)
[email protected]

🚀 Usage

Basic Example

import { Client, CommandHandler, EventHandler, loadEnv } from '@jdic/jcore'

const config = loadEnv()

const client = new Client({
  ownerNumber: config.botOwner,
  prefix: config.botPrefix,
})

;(async () =>
{
  await new CommandHandler(client).loadCommands()
  await new EventHandler(client).loadEvents()
  
  client.initialize()
})()

Creating a Command

Create a file in src/commands/utility/ping.ts:

import { CommandBuilder } from '@jdic/jcore'
import type { Command } from '@jdic/jcore'

export default
{
  data: new CommandBuilder()
    .setName('ping')
    .setDescription('Check bot latency')
    .setCategory('Utility')
    .setAliases(['p', 'latency'])
    .setCooldown(3)
    .build(),
    
  async execute({ message })
  {
    const start = Date.now()
    const reply = await message.reply('🏓 Pinging.. .')
    const latency = Date.now() - start
    
    await reply.edit(`🏓 Pong! Latency: ${latency}ms`)
  }
} as Command

Creating an Event

Create a file in src/events/ready.ts:

import { EventBuilder } from '@jdic/jcore'
import type { Event } from '@jdic/jcore'

export default {
  data: new EventBuilder()
    .setName('ready')
    .setOnce()
    .build(),

  async execute() {
    console.log('[STATUS] Bot is ready!')
  }
} as Event

📂 Project Structure

jcore/
├── src/
│   ├── builders/           # Command and Event builders
│   │   ├── CommandBuilder.ts
│   │   └── EventBuilder.ts
│   ├── commands/           # Bot commands (organized by category)
│   │   └── utility/
│   │       └── version.ts
│   ├── config/             # Configuration utilities
│   │   └── env.ts
│   ├── events/             # Event handlers
│   │   ├── ready.ts
│   │   └── message_create.ts
│   ├── handlers/           # Command and Event loaders
│   │   ├── CommandHandler.ts
│   │   └── EventHandler.ts
│   ├── structures/         # Core classes
│   │   ├── Client.ts       # Extended WhatsApp client
│   │   └── Collection.ts   # Enhanced Map utility
│   ├── types/              # TypeScript type definitions
│   │   ├── Command.ts
│   │   └── Event.ts
│   └── index.ts            # Main exports
├── tests/                  # Test files
│   ├── builders/
│   └── setup.ts
├── app.ts                  # Application entry point
├── package.json
├── tsconfig.json
└── README.md

🎨 Command Features

Command Options

Commands support typed options with validation:

data: new CommandBuilder()
  .setName('greet')
  .setDescription('Greet a user')
  .addOption({
    name: 'username',
    description: 'Name of the user',
    type: 'string',
    required: true,
    minLength: 2,
    maxLength: 50
  })
  .addOption({
    name: 'times',
    description: 'Number of times to greet',
    type: 'number',
    required: false,
    minValue: 1,
    maxValue: 10
  })
  .build()

Permission System

// Owner-only command
. setOwnerOnly(true)

// Group-only command
.setGroupOnly(true)

Cooldown System

// 5 second cooldown per user
.setCooldown(5)

Command Aliases

// Multiple ways to trigger the command
.setAliases(['p', 'ping', 'latency'])

🔧 API Reference

Client

const client = new Client({
  prefix: '!',
  ownerNumber: '[email protected]',
  commandsPath?: string,  // Optional custom commands directory
  eventsPath?: string     // Optional custom events directory
})

Properties:

  • client.commands - Collection of loaded commands
  • client.events - Collection of registered events
  • client.aliases - Command alias mappings
  • client.cooldowns - Cooldown tracking
  • client.prefix - Command prefix
  • client.ownerNumber - Bot owner's number

Collection

Enhanced Map with utility methods:

const collection = new Collection<string, number>()

collection.map((item) => item * 2)
collection.filter((item) => item > 5)
collection.find((item) => item === 10)
collection.partition((item) => item % 2 === 0)
collection.sweep((item) => item < 3)
collection.first()
collection.random()

CommandBuilder

new CommandBuilder()
  .setName(name: string)                    // Required
  .setDescription(description: string)       // Required
  .setCategory(category: string)
  .setAliases(aliases: string[])
  .setUsage(usage: string)
  .setCooldown(seconds: number)
  .setOwnerOnly(ownerOnly: boolean)
  .setGroupOnly(groupOnly: boolean)
  .addOption(option: CommandOption)
  .build()

EventBuilder

new EventBuilder()
  .setName(name: string)           // Required
  .setOnce(once: boolean = true)   // One-time event
  .build()

🧪 Testing

Run the test suite:

# Run all tests
bun test

# Watch mode
bun test --watch

Example test:

import { describe, test, expect } from 'bun: test'
import { CommandBuilder } from '@/builders/CommandBuilder'

describe('CommandBuilder', () =>
{
  test('should build a valid command', () =>
  {
    const command = new CommandBuilder()
      .setName('ping')
      .setDescription('Pong!')
      .build()

    expect(command.name).toBe('ping')
    expect(command.description).toBe('Pong!')
  })
})

📜 Scripts

# Development
bun start                 # Start the bot
bun run lint              # Lint code
bun run lint:fix          # Fix linting issues
bun test                  # Run tests
bun test: watch           # Run tests in watch mode

# Build & Publish
bun run build: dist       # Build distribution files
bun run package:check     # Dry-run package creation
bun run package:pack      # Create package tarball
bun run package:publish   # Publish to npm (requires auth)

📚 Documentation

Full documentation is available in the Wiki:

🛠️ Built With

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Made without ❤️ by jdic