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 🙏

© 2025 – Pkg Stats / Ryan Hefner

breezer.js

v0.5.3

Published

An elegant framework for discord.js :)

Downloads

77

Readme

BREEZER JS

An elegant framework for discord.js :)

Still under development (v0), only msgCreate is supported for now...

Features:

  • Typescript support
  • Simple and intuitive
  • State management more coming soon

Getting Started

Installation

npm i breezer.js
npm i discord.js@v13

Project setup

MyBot:
 --index.js
 --commands:
    --ping.js
    --calc.js
    --mul.js

A Basic Example

index.js :

import { Bot } from 'breezer.js'

const bot = new Bot({
    token: "<BOT_TOKEN>",
    prefix: "+",
    commandsFolder: "commands",
    // intents: []
});

bot.go(() => console.log('Logged In'));

It is as easy as its looks. commandsFolder folder is where all your commands will be stored. Everything else looks quite easy to follow up. Fill up some details and you're ready to go() !

Note: There is also an [optional] property to have custom intents (Breezer automatically sets the most common ones by default).

commands/ping.js :

import { Command } from 'breezer.js'

export default class extends Command<[]> {
    constructor() {
        super({
            structure: [],
            name: 'ping', // same as the file name
            strict: true // optional (def:false)
        });
    }

    async execute() {
        this.msg.reply({
            content: 'Pong!',
            allowedMentions: {
                repliedUser: false
            }
        });
    }
}

Every command is a class, child of the Command class. Generic of class Command<[]>: Defines the type of the structure of your cmd. - helps in inferring the types of different fields returned by this.extract() (explained later) structure - defines a structure for your command. Helpful when extracting the fields of you commands. This property will be better understood in the next command. Here there are no fields for this cmd => no structure.

*Reason why we define the structure twice is because, Generic helps in inferring the type properly and the property structure helps in actual conversion of field (say to number) and raising errors in strict mode.

strict - set it to true if you want to recieve errors/warnings when:

  • user does not follow the defined structure of the cmd
  • a deleted msg listens for certain state(s)
  • an expired msg listens for state(s).

This feature should only be turned on during development.

name - optional: will help in debugging in strict mode execute - logics for your command will be defined here.

commands/calc.js:

import { Command } from 'breezer.js'

export default class extends Command<[string]> {
    constructor() {
        super({
            structure: ['string'],
            name: 'calc'
        });
    }

    async execute() {
        // operation: string
        const [operation] = this.extract();
        let value;
        try {
            value = eval(operation);
        } catch (_) {
            value = 'Invalid Operation'
        }

        this.msg.channel.send(value.toString());
    }
}

Here structure has string as its first and only option. Now the user can easily extract the first option using this.extract.

Context: This string will be an expression 1*3 Warning: Never use eval like this, who knows what the operation is.

Structure can have these values:

"string", "string|null", "number", "number|null"

The nullable properties keep you safe in strict mode and while extracting.

Example of a structure:

["string", "number", "number", "string|null"]

Here a command will accept 4 options. If a user does not follow this structure in strict mode, it'll raise an error and you bot will stop. You can also easily extract these options:

// inside execute()
const [opt1, opt2, opt3, opt4] = this.extract();

NOTE: There can be only one nullable option, that too at the end.

commands/mul.js:

import { Command, StateManager } from 'breezer.js';
import { MessageEmbed } from 'discord.js';

const state = new StateManager({
    count: 1
});
export default class extends Command<[number]> {
    constructor() {
        super({
            name: 'mul',
            structure: ["number"],
            states: state.clone(),
            strict: true,
            till: 1
        });
    }
    async execute() {
        // by: number
        const [by] = this.extract();

        await this.send({
            embeds: [
                new MessageEmbed({
                    title: `${by} x $count$ = << ${by} * $count$ >>`
                })
            ]
        });
        
        setInterval(() => {
            this.states.set('count', p => p + 1);
        }, 1000);
    }
}

States are special values that when referred in message payload in a special way as string, update their reference in the original message as their value change.

We mention them inside strings using the $ reference, like this: $statename$.

We can also do operations on states, only when they lie inside << ... >>

// js methods
{
  content: "Answer is: << ['first', 'third'].includes('$answer$') >>"
}
// ternary operations
{
  content: "Count is: << $count$ > 5 : 'Big' :'Small' >>"
}
// arithmetic operations
{
  content: "Answer = << $num1$ + (($num2$ - 3) * 5)/10 >>"
  // yes, you can have 2 state in an operation!
}

Inside the constructor: states: this will be the instance of class StateManager. You can clone it to it independent or you can just refer the original object. till: msg listen to its state(s) for a certain time, define that time in minutes in this property. (default: 15min). Or set it to forever, it will always listen for the state(s).

This is what that example cmd (mul) looks in action:

state

HANDLERS

These are some extra functions available in the library to make stuff easier.

buttonSignal()

This handler is a syntactic-sugar for createMessageComponentCollector. This can be used in situations when one wants to collect button interactions when some specific users click the button.

import { buttonSignal } from 'breezer.js'

// inisde execute()
const sentMsg = this.msg.reply({
    components: [row]
});

buttonSignal(
    ['userid1', 'userid2'], // users
    sentMsg, // msg
    { max: 3, time: 2000 } // props (opt)

).on('collect', async btn => {
    await btn.deferUpdate();
    ...
}).on('end', async collection => {
    ...
});

/** 
 This signal will listen for 
    * max 3 clicks, for
    * 2 seconds, from
    * user with id 1 and 2 only, on
    * every button in the "row"
 */

So buttonSignal accepts 3 arguments

  • users: array containing the user id who can click the button (empty-array: anyone click the button)
  • msg: the message that contains the buttons
  • props: an optional parameter specifying these 3 properties-
    • customId: the only button from the row that you'll listen to (its id)
    • max: maximum valid clicks
    • time: the time interval (in ms) for which the button will be valid and clicks will matter

This function returns the normal discord's interaction listener listening for collect and end.

HasPerm Methods

A method and a function to check if the bot or any user has certain perm in the channel linked to a cmd's msg.

Inside a Command class (checks only for the bot)

this.botHasPerm( perm: PermissionResolvable ): boolean

Anywhere (checks for any user)

import { userHasPerm } from 'breezer.js';
userHasPerm( perm, userId: string, msg: Message ): Promise<boolean>