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

@developers-joyride/shortify

v2.1.0

Published

High performance URL shortener library with multi-database support (MongoDB, SQLite, PostgreSQL, MySQL)

Downloads

157

Readme

Shortify

A high-performance URL shortener library for Node.js, written in TypeScript with support for multiple databases (MongoDB, SQLite, PostgreSQL, MySQL).

Features

  • ⚡️ High performance: Optimized for high throughput
  • 🔒 Type safety: Full TypeScript support
  • 📈 Analytics: Track clicks and usage stats for your shortened URLs
  • ⌛️ Expiration support: Set expiration dates for your shortened URLs
  • 🛠️ Customizable: Use custom URL IDs or auto-generated ones
  • 🔄 Automatic retry: Built-in database connection retry with exponential backoff
  • 🧠 Unique URL IDs: Each shorten() call generates a unique URL ID, ensuring no conflicts
  • 🗄️ Multi-database support: Choose between MongoDB, SQLite, PostgreSQL, or MySQL
  • 🔧 Database abstraction: Easy to switch between databases without changing your code

Installation

# Using npm
npm i @developers-joyride/shortify

# Using yarn
yarn add @developers-joyride/shortify

Usage

Basic Usage

MongoDB (Original way - Backward Compatible)

import Shortify from "@developers-joyride/shortify";
import dotenv from "dotenv";

// Load environment variables
dotenv.config();

// Create a new Shortify instance with MongoDB (backward compatible)
const shortify = Shortify.createWithMongo(
  "https://your-domain.com/", // Base URL for your shortened links
  process.env.MONGODB_URI || "mongodb://localhost:27017/shortify" // MongoDB connection URI
);

// Connect to database
await shortify.connect();

// Shorten a URL
const result = await shortify.shorten(
  "https://example.com/very-long-url-that-needs-shortening"
);
console.log(`Shortened URL: ${result.shortUrl}`); // https://your-domain.com/abc123

// Resolve a shortened URL
const originalUrl = await shortify.resolve("abc123");
console.log(`Original URL: ${originalUrl}`); // https://example.com/very-long-url-that-needs-shortening

// Get statistics for a shortened URL
const stats = await shortify.getStats("abc123");
console.log(`Clicks: ${stats?.clicks}`);

// Delete a shortened URL
await shortify.delete("abc123");

// Disconnect when done
await shortify.disconnect();

SQLite

import Shortify, { DatabaseConfig } from "@developers-joyride/shortify";

const dbConfig: DatabaseConfig = {
  type: "sqlite",
  database: "./shortify.db", // Path to SQLite database file
  tableName: "my_custom_urls", // Optional: Custom table name (default: "urls")
  maxRetries: 3,
  retryDelay: 2000,
};

const shortify = new Shortify("https://your-domain.com/", dbConfig);
await shortify.connect();

// Use the same API as before
const result = await shortify.shorten("https://example.com/long-url");
console.log(`Shortened URL: ${result.shortUrl}`);

MongoDB (New Format)

import Shortify, { DatabaseConfig } from "@developers-joyride/shortify";

const dbConfig: DatabaseConfig = {
  type: "mongodb",
  connectionString: "mongodb://localhost:27017/shortify",
  collectionName: "my_custom_urls", // Optional: Custom collection name (default: "urls")
  maxRetries: 3,
  retryDelay: 2000,
};

const shortify = new Shortify("https://your-domain.com/", dbConfig);
await shortify.connect();

// Use the same API as before
const result = await shortify.shorten("https://example.com/long-url");
console.log(`Shortened URL: ${result.shortUrl}`);

Custom Collection/Table Names: You can specify custom collection names for MongoDB using the collectionName option, or custom table names for SQLite, PostgreSQL, and MySQL using the tableName option. This is useful when you want to organize your data differently or avoid conflicts with existing collections/tables. If not specified, they default to "urls".

Note: Collection and table names are now preserved exactly as specified, including case sensitivity. Previously, MongoDB collection names were automatically converted to lowercase, and SQL databases would convert unquoted table names to lowercase on case-insensitive filesystems.

MySQL

import Shortify, { DatabaseConfig } from "@developers-joyride/shortify";

const dbConfig: DatabaseConfig = {
  type: "mysql",
  host: "localhost",
  port: 3306,
  database: "shortify",
  username: "root",
  password: "your_password",
  tableName: "my_custom_urls", // Optional: Custom table name (default: "urls")
  maxRetries: 3,
  retryDelay: 2000,
};

const shortify = new Shortify("https://your-domain.com/", dbConfig);
await shortify.connect();

// Use the same API as before
const result = await shortify.shorten("https://example.com/long-url");
console.log(`Shortened URL: ${result.shortUrl}`);

PostgreSQL

import Shortify, { DatabaseConfig } from "@developers-joyride/shortify";

const dbConfig: DatabaseConfig = {
  type: "postgresql",
  host: "localhost",
  port: 5432,
  database: "shortify",
  username: "postgres",
  password: "your_password",
  tableName: "my_custom_urls", // Optional: Custom table name (default: "urls")
  maxRetries: 3,
  retryDelay: 2000,
};

const shortify = new Shortify("https://your-domain.com/", dbConfig);
await shortify.connect();

// Use the same API as before
const result = await shortify.shorten("https://example.com/long-url");
console.log(`Shortened URL: ${result.shortUrl}`);

Advanced Options

// Shorten a URL with custom options
const result = await shortify.shorten("https://example.com", {
  customUrlId: "custom-id", // Use a custom ID instead of auto-generated one
  urlLength: 6, // Set length of auto-generated ID (ignored if customUrlId is set)
  expiresInDays: 30, // URL will expire after 30 days
  baseUrl: "https://short.ly/", // Override the base URL for this specific link
});

// Each shorten() call generates a unique URL ID, even for the same original URL
const result1 = await shortify.shorten("https://example.com");
const result2 = await shortify.shorten("https://example.com");
console.log(result1.urlId !== result2.urlId); // true - different URL IDs
console.log(
  (await shortify.resolve(result1.urlId)) ===
    (await shortify.resolve(result2.urlId))
); // true - same original URL

// Create with connection options (MongoDB backward compatibility)
const shortify = Shortify.createWithMongo(
  "https://your-domain.com/",
  "mongodb://localhost:27017/shortify",
  {
    maxRetries: 5, // Maximum number of connection retry attempts
    retryDelay: 5000, // Initial delay between retries in ms (doubles with each retry)
    collectionName: "my_custom_urls", // Optional: Custom collection name (default: "urls")
  }
);

API Reference

Shortify Class

Constructor

constructor(baseUrl: string, dbConfig: DatabaseConfig)

Static Methods

  • createWithMongo(baseUrl: string, mongoUri: string, options?: { maxRetries?: number, retryDelay?: number }): Create instance with MongoDB (backward compatibility)

Instance Methods

  • connect(): Connect to database
  • disconnect(): Disconnect from database
  • isReady(): Check if the connection is established
  • shorten(url: string, options?: ShortifyOptions): Shorten a URL
  • resolve(urlId: string): Resolve a short URL to its original URL
  • getStats(urlId: string): Get statistics for a shortened URL
  • delete(urlId: string): Delete a shortened URL

DatabaseConfig Interface

interface DatabaseConfig {
  type: "mongodb" | "sqlite" | "postgresql" | "mysql";
  connectionString?: string; // For MongoDB
  database?: string; // For SQLite (file path) or PostgreSQL/MySQL (database name)
  host?: string; // For PostgreSQL/MySQL
  port?: number; // For PostgreSQL/MySQL
  username?: string; // For PostgreSQL/MySQL
  password?: string; // For PostgreSQL/MySQL
  maxRetries?: number; // Maximum connection retry attempts
  retryDelay?: number; // Initial delay between retries in ms
  collectionName?: string; // For MongoDB: Custom collection name (default: "urls")
  tableName?: string; // For SQLite/PostgreSQL/MySQL: Custom table name (default: "urls")
}

ShortifyOptions Interface

interface ShortifyOptions {
  baseUrl?: string; // Override the base URL
  urlLength?: number; // Length of the generated URL ID
  customUrlId?: string; // Custom URL ID
  expiresInDays?: number; // Number of days until the URL expires
}

Database Support

Shortify supports multiple database types, allowing you to choose the best option for your use case:

MongoDB

  • Best for: High-traffic applications, complex queries, horizontal scaling
  • Setup: Requires MongoDB server running
  • Configuration: Use connectionString parameter

SQLite

  • Best for: Simple applications, development, embedded systems
  • Setup: No server required, file-based
  • Configuration: Use database parameter (file path)

MySQL

  • Best for: Web applications, compatibility with existing MySQL infrastructure
  • Setup: Requires MySQL server running
  • Configuration: Use host, port, database, username, password parameters

PostgreSQL

  • Best for: ACID compliance, complex relationships, enterprise applications
  • Setup: Requires PostgreSQL server running
  • Configuration: Use host, port, database, username, password parameters

Examples

Check out the examples/ directory for comprehensive usage examples:

  • basic-usage.ts - Basic URL shortening functionality
  • sqlite-example.ts - SQLite database usage
  • postgresql-example.ts - PostgreSQL database usage
  • multi-database-usage.ts - Multi-database configuration examples
  • click-tracking-example.ts - Click tracking and analytics demonstration
  • express-server.ts - Express.js server integration
  • custom-collection-example.ts - Custom collection name demonstration
  • custom-table-names-example.ts - Custom table names for all database types

Click Tracking & Analytics

The library automatically tracks clicks when URLs are resolved. Here's a quick example:

// Create a shortened URL
const result = await shortify.shorten("https://example.com/my-page");

// Resolve the URL (this increments the click count)
const originalUrl = await shortify.resolve(result.urlId);

// Get statistics
const stats = await shortify.getStats(result.urlId);
console.log(`Clicks: ${stats?.clicks}`); // Will show 1
console.log(`Created: ${stats?.createdAt}`);
console.log(`Expires: ${stats?.expiresAt || "Never"}`);

For a comprehensive demonstration of click tracking features, run:

npx ts-node examples/click-tracking-example.ts

Migration Guide

From Previous Version

If you're upgrading from a previous version that only supported MongoDB, your code will continue to work without changes:

// Old way (still works)
const shortify = new Shortify(
  "https://your-domain.com/",
  "mongodb://localhost:27017/shortify"
);

// New way (recommended)
const shortify = Shortify.createWithMongo(
  "https://your-domain.com/",
  "mongodb://localhost:27017/shortify"
);

License

MIT