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

@hobenakicoffee/libraries

v6.5.0

Published

Framework-agnostic shared constants, utilities, types, and moderation tools for "হবে নাকি Coffee?" projects. **Version: 4.1.1**

Readme

@hobenakicoffee/libraries

Framework-agnostic shared constants, utilities, types, and moderation tools for "হবে নাকি Coffee?" projects. Version: 4.1.1

GitHub Stars GitHub Forks Watchers Branches Contributors Last commit Commits Open issues Closed issues Open PRs Closed PRs Merged PRs Release CI License npm Version npm Weekly Downloads npm Monthly Downloads npm Total Downloads npm Dependents npm Types npm Node npm License Package mgr · Bun Language · TypeScript Bundler · Vite OpenAI React Tailwind CSS Zod Biome VitePress ESM only Agent-friendly AGENTS.md

Installation

npm install @hobenakicoffee/libraries
# or
pnpm add @hobenakicoffee/libraries
# or
yarn add @hobenakicoffee/libraries
# or
bun add @hobenakicoffee/libraries

Usage

This package exposes multiple entry points. You can import from the main entry or specific submodules.

// Main entry - constants
import { PaymentStatuses, ServiceTypes, Visibility } from "@hobenakicoffee/libraries";

// Constants only
import { SupporterPlatforms } from "@hobenakicoffee/libraries/constants";

// Utilities only
import { formatAmount, formatDate, getUserPageLink } from "@hobenakicoffee/libraries/utils";

// Types only
import type { Database, Tables } from "@hobenakicoffee/libraries/types";

// Moderation tools
import { containsProfanity, containsBanglaSwear } from "@hobenakicoffee/libraries/moderation";

// URL state management
import { parseAsSortOrder } from "@hobenakicoffee/libraries/nuqs";

// Scripts
import { checkEnvEncryption } from "@hobenakicoffee/libraries/scripts";

// Hooks
import { useIsMobile } from "@hobenakicoffee/libraries/hooks";

Entry Points Overview

| Entrypoint | Description | | ---------- | ----------- | | @hobenakicoffee/libraries | Main entry - re-exports constants | | @hobenakicoffee/libraries/constants | All constants | | @hobenakicoffee/libraries/utils | Utility functions | | @hobenakicoffee/libraries/types | TypeScript types (custom + Supabase) | | @hobenakicoffee/libraries/moderation | Content moderation tools | | @hobenakicoffee/libraries/nuqs | URL state management parsers | | @hobenakicoffee/libraries/scripts | Build/utility scripts | | @hobenakicoffee/libraries/hooks | React hooks |


Constants (@hobenakicoffee/libraries/constants)

Visibility

import { Visibility } from "@hobenakicoffee/libraries";

Visibility.PUBLIC  // "public"
Visibility.PRIVATE // "private"

productInfo

Product metadata for "হবে নাকি Coffee?":

import { productInfo } from "@hobenakicoffee/libraries";

productInfo.name        // "হবে নাকি Coffee?"
productInfo.domain      // "https://www.hobenakicoffee.com"
productInfo.twitterHandle // "@hobenakicoffee"
productInfo.title       // Platform tagline
productInfo.description // Full description
productInfo.keywords    // SEO keywords
productInfo.socials     // Social media links object

companyInfo

Company contact and legal information:

import { companyInfo } from "@hobenakicoffee/libraries";

companyInfo.name           // "Shamscorner LLC"
companyInfo.contactEmail   // "[email protected]"
companyInfo.contactPhone   // "+1(817) 973-7285"
companyInfo.contactLocation // Full address
companyInfo.domain         // "https://www.shamscorner.com"
companyInfo.postalAddress  // Postal address object

Payment Constants

import { PaymentTypes, PaymentStatuses, PaymentProviders, PaymentDirections, PayoutProviders, WithdrawalStatuses } from "@hobenakicoffee/libraries";

// Payment Types
PaymentTypes.SUBSCRIPTION       // "subscription"
PaymentTypes.ONE_TIME           // "one-time"
PaymentTypes.PAYOUT             // "payout"
PaymentTypes.WITHDRAW_LOCK      // "withdraw_lock"
PaymentTypes.WITHDRAW_RELEASE   // "withdraw_release"
PaymentTypes.WITHDRAW_COMPLETE // "withdraw_complete"
PaymentTypes.MANUAL_ADJUSTMENT  // "manual_adjustment"

// Payment Statuses
PaymentStatuses.PENDING      // "pending"
PaymentStatuses.PROCESSING  // "processing"
PaymentStatuses.COMPLETED   // "completed"
PaymentStatuses.FAILED      // "failed"
PaymentStatuses.REVERSED    // "reversed"
PaymentStatuses.CANCELLED   // "cancelled"
PaymentStatuses.REFUNDED     // "refunded"
PaymentStatuses.REVIEWING    // "reviewing"

// Payment Providers
PaymentProviders.HOBENAKICOFFEE // "HobeNakiCoffee"
PaymentProviders.BKASH         // "Bkash"
PaymentProviders.NAGAD         // "Nagad"
PaymentProviders.ROCKET        // "Rocket"
PaymentProviders.UPAY          // "Upay"
PaymentProviders.SSLCOMMERZ    // "SSLCommerz"
PaymentProviders.AAMARPAY      // "Aamarpay"
PaymentProviders.PORTWALLET    // "Portwallet"
PaymentProviders.TAP           // "Tap"
PaymentProviders.OTHER         // "Other"

// Payment Directions
PaymentDirections.DEBIT  // "debit"
PaymentDirections.CREDIT // "credit"

// Payout Providers
PayoutProviders.BKASH   // "bkash"
PayoutProviders.NAGAD   // "nagad"
PayoutProviders.ROCKET // "rocket"
PayoutProviders.BANK   // "bank"

// Withdrawal Statuses
WithdrawalStatuses.REQUESTED  // "requested"
WithdrawalStatuses.APPROVED   // "approved"
WithdrawalStatuses.PROCESSING // "processing"
WithdrawalStatuses.PAID       // "paid"
WithdrawalStatuses.REJECTED   // "rejected"
WithdrawalStatuses.FAILED     // "failed"

Supporter Platforms

import { SupporterPlatforms } from "@hobenakicoffee/libraries";

SupporterPlatforms.FACEBOOK   // "facebook"
SupporterPlatforms.X          // "x"
SupporterPlatforms.INSTAGRAM  // "instagram"
SupporterPlatforms.YOUTUBE   // "youtube"
SupporterPlatforms.GITHUB     // "github"
SupporterPlatforms.LINKEDIN  // "linkedin"
SupporterPlatforms.TWITCH     // "twitch"
SupporterPlatforms.TIKTOK     // "tiktok"
SupporterPlatforms.THREADS    // "threads"
SupporterPlatforms.WHATSAPP   // "whatsapp"
SupporterPlatforms.TELEGRAM   // "telegram"
SupporterPlatforms.DISCORD    // "discord"
SupporterPlatforms.REDDIT     // "reddit"
SupporterPlatforms.PINTEREST  // "pinterest"
SupporterPlatformS.MEDIUM     // "medium"
SupporterPlatformS.DEVTO      // "devto"
SupporterPlatformS.BEHANCE    // "behance"
SupporterPlatformS.DRIBBBLE   // "dribbble"

Service Types

import { ServiceTypes } from "@hobenakicoffee/libraries";

ServiceTypes.GIFT              // "gift"
ServiceTypes.EXCLUSIVE_CONTENT // "exclusive_content"
ServiceTypes.WITHDRAWAL        // "withdrawal"
ServiceTypes.FOLLOW            // "follow"

Utilities (@hobenakicoffee/libraries/utils)

formatAmount

Formats a number as Bangladeshi Taka (৳).

import { formatAmount, formatSignedAmount } from "@hobenakicoffee/libraries/utils";

formatAmount(1000);    // "৳1,000"
formatAmount(-500);    // "৳500" (absolute value)

// With direction sign
formatSignedAmount(1000, "credit");  // "+ ৳1,000"
formatSignedAmount(500, "debit");   // "- ৳500"

formatCount

Formats a count with appropriate suffixes (K, M, B).

import { formatCount } from "@hobenakicoffee/libraries/utils";

formatCount(500);    // "500"
formatCount(1000);   // "1K"
formatCount(1500000); // "1.5M"

formatDate

Formats a date string to a readable format.

import { formatDate } from "@hobenakicoffee/libraries/utils";

formatDate("2024-01-15T00:00:00Z"); // "Jan 15, 2024"
formatDate("invalid");                // "-"

formatNumber

Formats a number with thousand separators.

import { formatNumber } from "@hobenakicoffee/libraries/utils";

formatNumber(1000000); // "1,000,000"

formatToPlainText

Converts various data types to plain text.

import { formatToPlainText, formatMetadataKey } from "@hobenakicoffee/libraries/utils";

// Basic usage
formatToPlainText("hello");           // "hello"
formatToPlainText(123);              // "123"
formatToPlainText(true);             // "Yes"
formatToPlainText(false);            // "No"

// With options
formatToPlainText("some long text...", { maxStringLength: 10 });
// "some lo..."

formatToPlainText({ key: "value" });
// JSON stringified

formatMetadataKey("supporterName");  // "Supporter Name"
formatMetadataKey("is_monthly");     // "Is monthly"

getUserPageLink

Generates a user profile page URL.

import { getUserPageLink } from "@hobenakicoffee/libraries/utils";

getUserPageLink("johndoe");
// "https://hobenakicoffee.com/@johndoe"

getUserPageLink("johndoe", "https://custom.com");
// "https://custom.com/@johndoe"

getProductLink

Generates a product page URL.

import { getProductLink } from "@hobenakicoffee/libraries/utils";

getProductLink("johndoe", "my-product");
// "https://hobenakicoffee.com/@johndoe/shop/products/my-product"

getProductLink("johndoe", "my-product", "https://custom.com");
// "https://custom.com/@johndoe/shop/products/my-product"

getNewsletterPostLink

Generates a newsletter post URL.

import { getNewsletterPostLink } from "@hobenakicoffee/libraries/utils";

getNewsletterPostLink("johndoe", "my-post");
// "/@johndoe/posts/my-post"

getNewsletterPostLink("johndoe", "my-post", "https://hobenakicoffee.com");
// "https://hobenakicoffee.com/@johndoe/posts/my-post"

getUserNameInitials

Extracts initials from a name.

import { getInitials } from "@hobenakicoffee/libraries/utils";

getInitials("John Doe");      // "JD"
getInitials("John");          // "J"
getInitials("John Michael");  // "JM"
getInitials(null);            // "?"

getSocialLink

Generates social media profile URLs.

import { getSocialLink, SupporterPlatforms } from "@hobenakicoffee/libraries";

getSocialLink("johndoe", SupporterPlatforms.FACEBOOK);
// "https://facebook.com/johndoe"

getSocialLink("johndoe", SupporterPlatforms.INSTAGRAM);
// "https://instagram.com/johndoe"

getSocialLink("johndoe", SupporterPlatforms.GITHUB);
// "https://github.com/johndoe"

getSocialHandle

Extracts the handle/username from a social media URL.

import { getSocialHandle } from "@hobenakicoffee/libraries/utils";

getSocialHandle("https://twitter.com/johndoe"); // "johndoe"
getSocialHandle("@johndoe");                     // "johndoe"
getSocialHandle("johndoe");                     // "johndoe"

openInNewWindow

Opens a URL in a new tab safely.

import { openInNewWindow } from "@hobenakicoffee/libraries/utils";

openInNewWindow("https://example.com");
// Opens in new tab with rel="noopener noreferrer"

Social Sharing Functions

import { shareToFacebook, shareToInstagram, shareToLinkedIn, shareToX } from "@hobenakicoffee/libraries/utils";

// Facebook
shareToFacebook({
  url: "https://example.com",
  quote: "Check this out!",
  hashtag: "coffee",
  ref: "campaign123"
});

// Instagram (uses Web Share API or copies to clipboard)
shareToInstagram({
  url: "https://example.com",
  text: "Check this out!"
});

// LinkedIn
shareToLinkedIn({
  url: "https://example.com",
  title: "My Title",
  summary: "Description here",
  source: "HobeNakiCoffee"
});

// X (Twitter)
shareToX({
  text: "Hello from HobeNakiCoffee!",
  url: "https://example.com",
  hashtags: "coffee,support",
  via: "hobenakicoffee"
});

QR Code Utilities

import { downloadQrSvgAsPng, printQrSvg } from "@hobenakicoffee/libraries/utils";

// Download QR as PNG
await downloadQrSvgAsPng(
  '<svg>...</svg>',
  "qr-code.png",
  () => console.log("Success"),
  () => console.log("Error")
);

// Print QR
printQrSvg(
  '<svg>...</svg>',
  "QR Code Print",
  () => console.log("Error")
);

toHumanReadable

Converts camelCase or snake_case strings to human-readable format.

import { toHumanReadable } from "@hobenakicoffee/libraries/utils";

toHumanReadable("camelCase");       // "Camel Case"
toHumanReadable("snake_case");      // "Snake Case"
toHumanReadable("CONSTANT_VALUE");  // "CONSTANT VALUE"
toHumanReadable("HTTPResponseCode"); // "HTTP Response Code"

validatePhoneNumber

Validates Bangladeshi mobile phone numbers.

import { validatePhoneNumber } from "@hobenakicoffee/libraries/utils";

validatePhoneNumber("01712345678");  // true
validatePhoneNumber("+8801712345678"); // true
validatePhoneNumber("8801712345678");  // true
validatePhoneNumber("01512345678");   // false (invalid prefix)
validatePhoneNumber("1234567890");    // false

checkModeration

Checks text for profanity using both local Bangla word lists and OpenAI moderation API.

import { checkModeration } from "@hobenakicoffee/libraries/utils";
import OpenAI from "openai";

const openai = new OpenAI();

const result = await checkModeration(openai, "some text to check");

result.flagged      // boolean - true if content is flagged
result.categories   // OpenAI categories if flagged
result.source      // "profanity" | "openai" | null
result.profaneWords // Array of matched profanity words (if from profanity check)
result.error        // Error if any

Moderation (@hobenakicoffee/libraries/moderation)

containsProfanity / containsBanglaSwear

Local profanity detection for English and Bangla.

import { containsProfanity, containsBanglaSwear, badwordsMatcher } from "@hobenakicoffee/libraries/moderation";

const hasProfanity = containsProfanity("some bad word here");
const hasBanglaProfanity = containsBanglaSwear("কিছু খারাপ শব্দ");

Types (@hobenakicoffee/libraries/types)

Full Supabase database types with Row, Insert, and Update types for each table.

import type { Database, Tables, TablesInsert, TablesUpdate, Enums } from "@hobenakicoffee/libraries/types";

// Database type
type DB = Database;

// Table row types
type Profile = Tables<"profiles">;
type Transaction = Tables<"transactions">;
type Supporter = Tables<"supporters">;

// Insert types
type NewProfile = TablesInsert<"profiles">;
type NewTransaction = TablesInsert<"transactions">;

// Update types
type ProfileUpdate = TablesUpdate<"profiles">;

// Enum types
type PaymentStatus = Enums<"payment_status_enum">;
type SupporterPlatform = Enums<"supporter_platform_enum">;

Custom Types

The library also exports custom types for common data structures:

import type { TransactionMetadata, ActivityMetadata, SupportersMetadata } from "@hobenakicoffee/libraries/types";

Nuqs (@hobenakicoffee/libraries/nuqs)

URL state management parsers using nuqs and zod.

import { parseAsSortOrder, parseAsDateRange, parseAsLastTimeRange } from "@hobenakicoffee/libraries/nuqs";

// Sort order
parseAsSortOrder.parse("asc"); // "asc"
parseAsSortOrder.parse("invalid"); // throws

// Date range
parseAsDateRange.parse({ from: new Date(), to: new Date() });

// Last time range
parseAsLastTimeRange.parse("last_7_days");
parseAsLastTimeRange.parse("last_30_days");
parseAsLastTimeRange.parse("last_90_days");
parseAsLastTimeRange.parse("last_180_days");
parseAsLastTimeRange.parse("last_year");

Hooks

useIsMobile

React hook to detect if the viewport is mobile-sized.

import { useIsMobile } from "@hobenakicoffee/libraries/hooks";

function MyComponent() {
  const isMobile = useIsMobile();
  
  return <div>{isMobile ? "Mobile" : "Desktop"}</div>;
}

API Reference

Constants

| Export | Type | Description | |--------|------|-------------| | Visibility | object | PUBLIC, PRIVATE constants | | Visibility | type | Type for visibility values | | productInfo | object | Product metadata | | companyInfo | object | Company information | | PaymentTypes | object | Payment type constants | | PaymentType | type | Type for payment types | | PaymentStatuses | object | Payment status constants | | PaymentStatus | type | Type for payment statuses | | PaymentProviders | object | Payment provider constants | | PaymentProvider | type | Type for payment providers | | PaymentDirections | object | Payment direction constants | | PaymentDirection | type | Type for payment directions | | PayoutProviders | object | Payout provider constants | | PayoutProvider | type | Type for payout providers | | WithdrawalStatuses | object | Withdrawal status constants | | WithdrawalStatus | type | Type for withdrawal statuses | | SupporterPlatforms | object | Social platform constants | | SupporterPlatform | type | Type for supporter platforms | | ServiceTypes | object | Service type constants | | ServiceType | type | Type for service types |

Utilities

| Function | Description | |----------|-------------| | formatAmount | Format number as ৳ currency | | formatSignedAmount | Format with + or - sign | | formatCount | Format count with K, M, B suffixes | | formatDate | Format date string | | formatNumber | Format with thousand separators | | formatToPlainText | Convert value to plain text | | formatMetadataKey | Format metadata key to readable text | | getUserPageLink | Generate user profile URL | | getProductLink | Generate product page URL | | getNewsletterPostLink | Generate newsletter post URL | | getInitials | Get name initials | | getSocialLink | Generate social profile URL | | getSocialHandle | Extract handle from social URL | | openToNewWindow | Open URL in new tab | | postToFacebook | Share to Facebook | | postToInstagram | Share to Instagram | | postToLinkedIn | Share to LinkedIn | | postToX | Share to X (Twitter) | | downloadQrSvgAsPng | Download QR as PNG | | printQrSvg | Print QR code | | toHumanReadable | Convert camelCase/snake_case to readable | | validatePhoneNumber | Validate Bangladeshi phone | | checkModeration | Check text for profanity |

Moderation

| Function | Description | |----------|-------------| | containsProfanity | Check text for profanity (English + Bangla) | | containsBanglaSwear | Check text for Bangla profanity | | badwordsMatcher | English profanity matcher (obscenity) | | banglaBadWords | Bangla profanity word list |


Local Development

Install dependencies:

bun install

Available scripts:

# Build the library
bun run build

# Run in watch mode during development
bun run dev

# Run tests
bun run test

# Run tests in watch mode
bun run test:watch

# Run type checking
bun run typecheck

# Alias for typecheck
bun run lint

# Format code
bun run format

# Check formatting
bun run format:check

# Check formatting issues
bun run format:doctor

# Clean build artifacts
bun run clean

Project Structure

src/
├── index.ts                 # Main entry (re-exports constants)
├── constants/
│   ├── common.ts           # Visibility
│   ├── legal.ts            # productInfo, companyInfo
│   ├── payment.ts          # Payment constants
│   ├── platforms.ts        # SupporterPlatforms
│   ├── services.ts         # ServiceTypes
│   └── index.ts            # Exports
├── utils/
│   ├── check-moderation.ts
│   ├── format-amount.ts
│   ├── format-count.ts
│   ├── format-date.ts
│   ├── format-number.ts
│   ├── format-plain-text.ts
│   ├── get-newsletter-post-link.ts
│   ├── get-product-link.ts
│   ├── get-social-handle.ts
│   ├── get-social-link.ts
│   ├── get-user-name-initials.ts
│   ├── get-user-page-link.ts
│   ├── open-to-new-window.ts
│   ├── post-to-facebook.ts
│   ├── post-to-instagram.ts
│   ├── post-to-linkedin.ts
│   ├── post-to-x.ts
│   ├── qr-svg-utils.ts
│   ├── to-human-readable.ts
│   ├── validate-phone-number.ts
│   └── index.ts            # Exports
├── moderation/
│   ├── datasets/
│   │   ├── bn.ts           # Bangla bad words
│   │   └── index.ts
│   ├── profanity-service.ts
│   └── index.ts            # Exports
├── types/
│   ├── supabase.ts         # Full Supabase types
│   └── index.ts            # Exports + custom types
├── nuqs/
│   ├── common.ts           # URL state parsers
│   └── index.ts            # Exports
├── hooks/
│   └── use-mobile.ts       # Mobile detection hook
└── scripts/
    ├── check-env-encryption.ts
    └── index.ts            # Exports

Dependencies

Runtime

  • @fontsource-variable/noto-sans-bengali - Bengali font
  • class-variance-authority - Component variants
  • clsx - Class name utility
  • nuqs - URL state management
  • obscenity - Profanity detection
  • openai - OpenAI API
  • react / react-dom - React
  • tailwind-merge - Tailwind merge
  • tailwindcss - Styling
  • tw-animate-css - Animations
  • zod - Schema validation

Dev

  • @biomejs/biome - Linting/formatting
  • ultracite - Ultracite CLI
  • vite - Build tool

Release & Publish

Publishing is automated on push to the main branch via GitHub Actions. Ensure:

  • package.json version is updated.
  • NPM_TOKEN secret is configured with publish permissions.

For local publish (if needed):

npm publish --access public