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

@qazuor/qzpay-cli

v1.1.0

Published

CLI for scaffolding QZPay billing setups

Readme

@qazuor/qzpay-cli

CLI for scaffolding QZPay billing setups. Generate production-ready billing code with interactive prompts.

Features

  • Interactive project scaffolding with beautiful prompts
  • Support for Stripe and MercadoPago payment providers
  • Framework integrations: Hono, NestJS, or library-only
  • Multiple billing models: subscriptions, one-time payments, usage-based, marketplace
  • TypeScript-first with full type definitions
  • Ready-to-run generated code

Installation

# Global installation
npm install -g @qazuor/qzpay-cli

# Or use directly with npx
npx @qazuor/qzpay-cli init

# Or with pnpm
pnpm dlx @qazuor/qzpay-cli init

Quick Start

# Run the interactive setup
qzpay init

# Or specify output directory
qzpay init -d ./my-billing

Command Reference

qzpay init

Scaffold a complete QZPay billing setup with interactive prompts.

qzpay init [options]

Options:
  -d, --dir <directory>  Output directory (default: ".")
  -y, --yes              Skip prompts and use defaults
  -h, --help             Display help

Interactive Prompts

The CLI guides you through these configuration steps:

1. Project Info

◆  Project name
│  my-billing
│
◆  Output directory
│  ./billing
│
◆  Project description (optional)
│  Billing system for my SaaS

2. Payment Provider

◆  Payment provider
│  ○ Stripe (Recommended for most use cases)
│  ○ MercadoPago (Best for Latin America)
│  ○ Both (Multi-provider setup)

3. Storage Adapter

◆  Storage adapter
│  ○ Drizzle (PostgreSQL) - Production-ready
│  ○ In-memory - Development/testing only

4. Framework

◆  Framework integration
│  ○ Hono - Fast, lightweight web framework
│  ○ NestJS - Enterprise Node.js framework
│  ○ Library only - No HTTP layer

5. Features

◆  Features to include (multi-select)
│  ◼ Subscriptions - Recurring billing
│  ◻ One-time payments - Single purchases
│  ◻ Usage-based billing - Metered usage
│  ◻ Marketplace - Multi-vendor support
│  ◻ Add-ons - Subscription add-ons

6. Plan Structure

◆  Use predefined plan structure?
│  Yes
│
◆  Plan structure
│  ○ Freemium (Free + Pro + Enterprise)
│  ○ Tiered (Basic + Professional + Agency)
│  ○ Usage-based (Starter + Growth + Business + Enterprise)

Or define custom plans with name, display name, monthly price, and yearly price.

Generated Files

Based on your selections, the CLI generates:

Core Files (Always Generated)

| File | Description | |------|-------------| | qzpay.config.ts | Database connection, payment provider setup, QZPayBilling initialization, event listeners | | .env.example | Template with all required environment variables | | types.ts | TypeScript types: plan tiers, limits, pricing constants, customer interface | | plans.ts | Plan initialization script with price creation | | services.ts | Business logic: customer registration, subscriptions, payments |

Framework-Specific Files

Hono

| File | Description | |------|-------------| | routes.ts | API routes with middleware, billing routes, custom endpoints | | webhooks.ts | Webhook handlers for payment events |

NestJS

| File | Description | |------|-------------| | billing.module.ts | Dynamic NestJS module with forRoot and forRootAsync | | billing.service.ts | Injectable service wrapping QZPayBilling | | webhooks.controller.ts | Controller for webhook endpoints | | webhooks.ts | Webhook handler functions |

Example Output

Generated qzpay.config.ts

import { QZPayBilling } from '@qazuor/qzpay-core';
import { QZPayDrizzleStorageAdapter } from '@qazuor/qzpay-drizzle';
import { QZPayStripeAdapter } from '@qazuor/qzpay-stripe';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import Stripe from 'stripe';

// Environment validation
function getEnvVar(name: string): string {
    const value = process.env[name];
    if (!value) throw new Error(`Missing: ${name}`);
    return value;
}

// Database
const client = postgres(getEnvVar('DATABASE_URL'));
export const db = drizzle(client);

// Stripe
export const stripe = new Stripe(getEnvVar('STRIPE_SECRET_KEY'), {
    apiVersion: '2024-12-18.acacia'
});

// Adapters
export const storageAdapter = new QZPayDrizzleStorageAdapter({ db, livemode: process.env.NODE_ENV === 'production' });
export const stripeAdapter = new QZPayStripeAdapter({ client: stripe, livemode: process.env.NODE_ENV === 'production' });

// Billing instance
export const billing = new QZPayBilling({
    storage: storageAdapter,
    provider: stripeAdapter,
    livemode: process.env.NODE_ENV === 'production'
});

// Event listeners
billing.on('subscription.created', async (event) => {
    console.log(`New subscription: ${event.data.id}`);
});

export default billing;

Generated types.ts

// Plan tiers
export type MyBillingPlanTier = 'free' | 'pro' | 'enterprise';

// Customer interface
export interface MyBillingCustomer {
    id: string;
    email: string;
    name: string;
    planTier: MyBillingPlanTier;
    createdAt: Date;
}

// Plan limits
export const MY_BILLING_PLAN_LIMITS: Record<MyBillingPlanTier, MyBillingPlanLimits> = {
    free: { maxItems: 5, maxUsers: 1, features: { analytics: false } },
    pro: { maxItems: 50, maxUsers: 10, features: { analytics: true } },
    enterprise: { maxItems: -1, maxUsers: -1, features: { analytics: true } }
};

// Pricing (in cents)
export const MY_BILLING_PRICING = {
    plans: {
        free: { monthly: 0, yearly: 0 },
        pro: { monthly: 1999, yearly: 19990 },
        enterprise: { monthly: 9999, yearly: 99990 }
    }
} as const;

Complete Workflow Example

# 1. Create new billing project
qzpay init -d ./my-saas-billing

# 2. Navigate to directory
cd my-saas-billing

# 3. Copy environment template
cp .env.example .env

# 4. Edit .env with your credentials
# DATABASE_URL=postgresql://user:pass@localhost:5432/mydb
# STRIPE_SECRET_KEY=sk_test_...
# STRIPE_WEBHOOK_SECRET=whsec_...

# 5. Install dependencies (in your project)
pnpm add @qazuor/qzpay-core @qazuor/qzpay-stripe @qazuor/qzpay-drizzle
pnpm add stripe drizzle-orm postgres

# 6. Run database migrations
pnpm drizzle-kit push

# 7. Initialize plans in Stripe
npx tsx plans.ts

# 8. Start the server (Hono)
npx tsx routes.ts

# Server running on http://localhost:3000
# Webhooks: POST http://localhost:3000/webhooks/stripe

Configuration by Use Case

SaaS with Subscriptions

Provider: Stripe
Storage: Drizzle
Framework: Hono
Features: Subscriptions, Add-ons
Plans: Freemium (Free + Pro + Enterprise)

E-commerce in Latin America

Provider: MercadoPago
Storage: Drizzle
Framework: NestJS
Features: One-time payments
Plans: Custom (single product pricing)

Usage-Based API

Provider: Stripe
Storage: Drizzle
Framework: Hono
Features: Subscriptions, Usage-based billing
Plans: Usage-based (Starter + Growth + Business + Enterprise)

Multi-Vendor Marketplace

Provider: Both (Stripe for vendors, MercadoPago for buyers)
Storage: Drizzle
Framework: Hono
Features: Subscriptions, Marketplace
Plans: Tiered (for vendors)

Troubleshooting

"Missing environment variable" error

Ensure all required variables are set in your .env file. Check .env.example for the complete list.

Webhook signature verification fails

  1. Make sure STRIPE_WEBHOOK_SECRET matches your Stripe dashboard
  2. For local development, use Stripe CLI: stripe listen --forward-to localhost:3000/webhooks/stripe

Plans not creating

  1. Verify your Stripe API key is valid
  2. Check if you're using test vs live keys
  3. Run plans.ts with DEBUG=* for verbose output

TypeScript errors after generation

  1. Install all peer dependencies
  2. Run pnpm typecheck to see specific errors
  3. Ensure TypeScript version >= 5.0

Environment Variables Reference

| Variable | Required | Description | |----------|----------|-------------| | DATABASE_URL | Drizzle | PostgreSQL connection string | | STRIPE_SECRET_KEY | Stripe | Stripe API secret key | | STRIPE_WEBHOOK_SECRET | Stripe | Stripe webhook signing secret | | STRIPE_PUBLISHABLE_KEY | Stripe | Stripe publishable key (frontend) | | MERCADOPAGO_ACCESS_TOKEN | MercadoPago | MercadoPago access token | | MERCADOPAGO_WEBHOOK_SECRET | MercadoPago | MercadoPago webhook secret | | PORT | Hono/NestJS | Server port (default: 3000) | | NODE_ENV | All | Environment: development/production | | JWT_SECRET | Hono/NestJS | JWT signing secret |

API Reference

Generated Service Functions

// Customer management
registerCustomer({ email, name, planTier? }): Promise<Customer>
getCustomer(customerId): Promise<Customer | null>
getCustomerLimits(planTier): PlanLimits

// Subscriptions
subscribeToPlan(customerId, planTier, interval?): Promise<{ subscriptionId, checkoutUrl }>
changePlan(customerId, newTier, interval?): Promise<void>
cancelSubscription(customerId, immediately?): Promise<void>

// Add-ons (if enabled)
addAddOn(customerId, addOnKey): Promise<void>
removeAddOn(customerId, addOnKey): Promise<void>

// One-time (if enabled)
purchaseService(customerId, serviceKey): Promise<{ paymentId, checkoutUrl }>

// Usage tracking (if enabled)
trackUsage(customerId, metric, quantity): Promise<void>
checkUsageLimit(customerId, metric): Promise<{ allowed, used, limit }>
getUsageSummary(customerId): Promise<UsageSummary>

// Payments
getPaymentHistory(customerId): Promise<Payment[]>
getInvoices(customerId): Promise<Invoice[]>

Related Packages

License

MIT