mk-cts
v1.0.3
Published
A lightweight, type-safe utility library for building Core-Tenant-System applications with TypeScript
Maintainers
Readme
Core-Tenant-System
A lightweight, type-safe utility library for building Core-Tenant-System applications with TypeScript
📦 Installation
npm install mk-ctsyarn add mk-ctspnpm 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 tenantdbName?(string): Optional custom database namemetadata?(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-proneAfter (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.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - 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!
