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

mk-cts

v1.0.3

Published

A lightweight, type-safe utility library for building Core-Tenant-System applications with TypeScript

Readme

Core-Tenant-System

A lightweight, type-safe utility library for building Core-Tenant-System applications with TypeScript

npm version License: MIT TypeScript

📦 Installation

npm install mk-cts
yarn add mk-cts
pnpm add mk-cts

✨ Features

  • 🔒 Type-safe: Written in TypeScript with full type definitions
  • 🪶 Lightweight: Zero dependencies, minimal bundle size
  • 🚀 Easy to use: Simple and intuitive API
  • 🏗️ Multi-tenant ready: Built specifically for multi-tenant architectures
  • 📦 Tree-shakeable: ESM and CommonJS support
  • 🧪 Well-tested: Comprehensive test coverage (coming soon)

🎯 Use Cases

  • Building SaaS applications with tenant isolation
  • Managing multiple databases per tenant
  • Tenant provisioning and management
  • Multi-tenant API development

🚀 Quick Start

import { TenantManager } from 'mk-cts';

// Create a tenant manager instance
const manager = new TenantManager({
  cacheEnabled: true,
  cacheTTL: 3600
});

// Create a new tenant
const tenant = await manager.createTenant({
  slug: 'acme-corp',
  name: 'Acme Corporation',
  metadata: {
    plan: 'enterprise',
    maxUsers: 100
  }
});

console.log(tenant);
// {
//   id: 'tnt_a1b2c3d4e5f6...',
//   slug: 'acme-corp',
//   name: 'Acme Corporation',
//   status: 'active',
//   createdAt: 2024-01-01T00:00:00.000Z,
//   updatedAt: 2024-01-01T00:00:00.000Z,
//   metadata: { plan: 'enterprise', maxUsers: 100 }
// }

📖 API Documentation

TenantManager

Main class for managing tenant operations.

Constructor

new TenantManager(options?: TenantManagerOptions)

Options:

  • autoProvision?: boolean - Automatically provision resources (default: true)
  • cacheEnabled?: boolean - Enable tenant caching (default: true)
  • cacheTTL?: number - Cache time-to-live in seconds (default: 3600)

Methods

createTenant(config: TenantConfig): Promise<Tenant>

Create a new tenant.

const tenant = await manager.createTenant({
  slug: 'my-company',
  name: 'My Company Inc.',
  metadata: { tier: 'pro' }
});

Parameters:

  • slug (string): Unique tenant identifier (lowercase, alphanumeric, hyphens only)
  • name (string): Display name for the tenant
  • dbName? (string): Optional custom database name
  • metadata? (object): Optional metadata

Returns: Promise<Tenant>

Throws: Error if slug is invalid or already exists


getTenant(slug: string): Tenant | undefined

Retrieve a tenant by slug.

const tenant = manager.getTenant('my-company');

listTenants(): Tenant[]

Get all tenants.

const allTenants = manager.listTenants();

updateTenant(slug: string, updates: Partial<TenantConfig>): Tenant | undefined

Update tenant information.

const updated = manager.updateTenant('my-company', {
  name: 'My Company LLC',
  metadata: { tier: 'enterprise' }
});

deleteTenant(slug: string): boolean

Delete a tenant.

const deleted = manager.deleteTenant('my-company');

Returns: true if deleted, false if not found


DatabaseHelper

Utility class for database operations in multi-tenant environments.

Constructor

new DatabaseHelper(config: DatabaseConnectionConfig)

Config:

{
  host: string;
  port: number;
  username: string;
  password: string;
  database?: string;
}

Methods

static generateDatabaseName(tenantSlug: string, prefix?: string): string

Generate a database name for a tenant.

const dbName = DatabaseHelper.generateDatabaseName('acme-corp', 'tenant_');
// Returns: 'tenant_acme_corp'

getConnectionString(dbName: string): string

Build a PostgreSQL connection string.

const helper = new DatabaseHelper({
  host: 'localhost',
  port: 5432,
  username: 'admin',
  password: 'secret'
});

const connStr = helper.getConnectionString('tenant_acme_corp');
// Returns: 'postgresql://admin:secret@localhost:5432/tenant_acme_corp'

validateConfig(): boolean

Validate the database configuration.

const isValid = helper.validateConfig();

Utility Functions

validateTenantSlug(slug: string): ValidationResult

Validate a tenant slug format.

import { validateTenantSlug } from 'Core-Tenant-System';

const result = validateTenantSlug('my-company');
// { valid: true }

const invalid = validateTenantSlug('My Company!');
// { valid: false, error: 'Slug must contain only lowercase letters...' }

Slug rules:

  • 3-50 characters
  • Lowercase letters, numbers, and hyphens only
  • Cannot start or end with a hyphen
  • No consecutive hyphens

generateTenantId(prefix?: string): string

Generate a unique tenant ID.

import { generateTenantId } from 'Core-Tenant-System';

const id = generateTenantId(); // 'tnt_a1b2c3d4e5f6789...'
const customId = generateTenantId('org_'); // 'org_x9y8z7w6v5u4...'

sanitizeTenantSlug(input: string): string

Sanitize and normalize a string to a valid tenant slug.

import { sanitizeTenantSlug } from 'Core-Tenant-System';

const slug = sanitizeTenantSlug('My Company Name!');
// Returns: 'my-company-name'

isValidTenantId(id: string): boolean

Check if a string is a valid tenant ID.

import { isValidTenantId } from 'Core-Tenant-System';

isValidTenantId('tnt_a1b2c3d4e5f6789012345678'); // true
isValidTenantId('invalid-id'); // false

📘 TypeScript Types

Tenant

interface Tenant {
  id: string;
  slug: string;
  name: string;
  status: 'active' | 'inactive' | 'suspended';
  createdAt: Date;
  updatedAt: Date;
  metadata?: Record<string, any>;
}

TenantConfig

interface TenantConfig {
  slug: string;
  name: string;
  dbName?: string;
  metadata?: Record<string, any>;
}

DatabaseConnectionConfig

interface DatabaseConnectionConfig {
  host: string;
  port: number;
  username: string;
  password: string;
  database?: string;
}

TenantManagerOptions

interface TenantManagerOptions {
  autoProvision?: boolean;
  cacheEnabled?: boolean;
  cacheTTL?: number;
}

ValidationResult

interface ValidationResult {
  valid: boolean;
  error?: string;
}

🔧 Advanced Usage

Complete Example

import {
  TenantManager,
  DatabaseHelper,
  validateTenantSlug,
  sanitizeTenantSlug,
  generateTenantId
} from 'Core-Tenant-System';

// Initialize tenant manager
const tenantManager = new TenantManager({
  cacheEnabled: true,
  cacheTTL: 7200
});

// Initialize database helper
const dbHelper = new DatabaseHelper({
  host: process.env.DB_HOST || 'localhost',
  port: 5432,
  username: process.env.DB_USER || 'admin',
  password: process.env.DB_PASSWORD || 'password'
});

// User input sanitization
const userInput = 'Acme Corporation!!!';
const sanitized = sanitizeTenantSlug(userInput); // 'acme-corporation'

// Validation
const validation = validateTenantSlug(sanitized);
if (!validation.valid) {
  throw new Error(validation.error);
}

// Create tenant
const tenant = await tenantManager.createTenant({
  slug: sanitized,
  name: 'Acme Corporation',
  metadata: {
    industry: 'Technology',
    employeeCount: 50
  }
});

// Generate database name
const dbName = DatabaseHelper.generateDatabaseName(tenant.slug);

// Get connection string
const connectionString = dbHelper.getConnectionString(dbName);

console.log('Tenant created:', tenant);
console.log('Database:', dbName);
console.log('Connection:', connectionString);

// Update tenant
const updated = tenantManager.updateTenant(tenant.slug, {
  metadata: {
    ...tenant.metadata,
    employeeCount: 75
  }
});

// List all tenants
const allTenants = tenantManager.listTenants();
console.log('Total tenants:', allTenants.length);

🔄 Migration from Other Libraries

If you're migrating from another multi-tenant solution, here's a comparison:

Before (generic approach)

const tenantId = generateRandomId();
const dbName = `tenant_${tenantId.replace(/-/g, '_')}`;
// Manual validation, error-prone

After (with mk-core-tenant-ststem)

import { TenantManager, DatabaseHelper } from 'Core-Tenant-System';

const manager = new TenantManager();
const tenant = await manager.createTenant({ slug: 'my-tenant', name: 'My Tenant' });
const dbName = DatabaseHelper.generateDatabaseName(tenant.slug);
// Type-safe, validated, consistent

🛠️ Requirements

  • Node.js >= 14.0.0
  • TypeScript >= 4.5.0 (for TypeScript projects)

📝 License

MIT © Mohamed Khaled


🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

🐛 Issues

Found a bug? Have a feature request? Please open an issue.


📚 Resources


⭐ Show Your Support

Give a ⭐️ if this project helped you!