High performance URL shortener library with multi-database support (MongoDB, SQLite, PostgreSQL, MySQL)
npm install @developers-joyride/shortifyA high-performance URL shortener library for Node.js, written in TypeScript with support for multiple databases (MongoDB, SQLite, PostgreSQL, MySQL).
- ⚡️ 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
``bashUsing npm
npm i @developers-joyride/shortify
Usage
$3
#### MongoDB (Original way - Backward Compatible)
`typescript
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
`typescript
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)
`typescript
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
`typescript
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
`typescript
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});
`$3
`typescript
// 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
$3
#### Constructor
`typescript
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$3
`typescript
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")
}
`$3
`typescript
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:
$3
- Best for: High-traffic applications, complex queries, horizontal scaling
- Setup: Requires MongoDB server running
- Configuration: Use
connectionString parameter$3
- Best for: Simple applications, development, embedded systems
- Setup: No server required, file-based
- Configuration: Use
database parameter (file path)$3
- Best for: Web applications, compatibility with existing MySQL infrastructure
- Setup: Requires MySQL server running
- Configuration: Use
host, port, database, username, password parameters$3
- Best for: ACID compliance, complex relationships, enterprise applications
- Setup: Requires PostgreSQL server running
- Configuration: Use
host, port, database, username, password parametersExamples
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$3
The library automatically tracks clicks when URLs are resolved. Here's a quick example:
`typescript
// 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:
`bash
npx ts-node examples/click-tracking-example.ts
`Migration Guide
$3
If you're upgrading from a previous version that only supported MongoDB, your code will continue to work without changes:
`typescript
// 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"
);
``MIT