Interfaces
The NestJS Multitenant package provides comprehensive TypeScript interfaces that are tailored to your chosen ORM. The ORM abstraction layer ensures type safety while allowing flexibility between TypeORM and Drizzle.
ORM Abstraction Interfaces
IOrmConnection
Base interface for all ORM connections.
interface IOrmConnection {
type: 'typeorm' | 'drizzle';
getTenantId(): string;
getDatabase(): any; // TypeORM DataSource or Drizzle NodePgDatabase
close(): Promise<void>;
isConnected(): boolean;
}
IOrmStrategy
Strategy interface for ORM-specific operations.
interface IOrmStrategy {
type: 'typeorm' | 'drizzle';
createConnection(tenantId: string): Promise<IOrmConnection>;
validateConnection(connection: IOrmConnection): boolean;
closeConnection(connection: IOrmConnection): Promise<void>;
}
OrmConfig
Configuration interface for ORM selection and options.
interface OrmConfig {
type: 'typeorm' | 'drizzle';
drizzle?: {
schema: Record<string, any>; // Drizzle schema objects
logger?: boolean;
ssl?: boolean | object;
};
typeorm?: {
autoLoadEntities?: boolean;
synchronize?: boolean;
logging?: boolean;
ssl?: boolean | object;
retryAttempts?: number;
retryDelay?: number;
};
}
Drizzle ORM Specific Interfaces
IDrizzleConnection
Drizzle-specific connection interface.
interface IDrizzleConnection extends IOrmConnection {
type: 'drizzle';
getDatabase(): NodePgDatabase<any>;
getSchema(): Record<string, any>;
}
DrizzleConnectionOptions
Options for Drizzle database connections.
interface DrizzleConnectionOptions {
schema: Record<string, any>;
logger?: boolean;
ssl?: boolean | object;
}
TypeORM Specific Interfaces
ITypeOrmConnection
TypeORM-specific connection interface.
interface ITypeOrmConnection extends IOrmConnection {
type: 'typeorm';
getDatabase(): DataSource;
getRepository<Entity>(entityClass: any): Repository<Entity>;
}
TypeOrmConnectionOptions
Options for TypeORM database connections.
interface TypeOrmConnectionOptions {
autoLoadEntities?: boolean;
synchronize?: boolean;
logging?: boolean;
ssl?: boolean | object;
retryAttempts?: number;
retryDelay?: number;
}
Core Module Interfaces
MultiTenantModuleOptions
Main configuration interface for the multi-tenant module.
interface MultiTenantModuleOptions {
// Database configuration
database: DatabaseConfig;
// ORM configuration
orm?: OrmConfig; // Defaults to TypeORM for backward compatibility
// Platform configuration
platform: 'express' | 'fastify';
// Schema management
autoCreateSchemas?: boolean;
// Admin module
enableAdminModule?: boolean;
// Tenant resolution
tenantResolution?: TenantResolutionConfig;
// Validation strategies
validationStrategies?: ValidationStrategyConfig[];
// Custom providers and controllers
customProviders?: Provider[];
customControllers?: ClassConstructor<any>[];
}
DatabaseConfig
Database connection configuration.
interface DatabaseConfig {
host: string;
port: number;
username: string;
password: string;
database: string;
ssl?: boolean | object;
}
TenantResolutionConfig
Configuration for tenant resolution strategies.
interface TenantResolutionConfig {
strategy: 'header' | 'subdomain' | 'query' | 'custom';
headerName?: string; // For header strategy
queryParam?: string; // For query strategy
subdomainSeparator?: string; // For subdomain strategy
customProvider?: Provider; // For custom strategy
}
Tenant Management Interfaces
ITenant
Core tenant entity interface.
interface ITenant {
id: string;
name: string;
domain?: string;
subdomain?: string;
database: string;
schema: string;
isActive: boolean;
createdAt: Date;
updatedAt: Date;
}
CreateTenantDto
Data transfer object for creating tenants.
interface CreateTenantDto {
name: string;
domain?: string;
subdomain?: string;
isActive?: boolean;
metadata?: Record<string, any>;
}
UpdateTenantDto
Data transfer object for updating tenants.
interface UpdateTenantDto {
name?: string;
domain?: string;
subdomain?: string;
isActive?: boolean;
metadata?: Record<string, any>;
}
ListTenantDto
Data transfer object for listing tenants.
interface ListTenantDto {
search?: string;
isActive?: boolean;
page?: number;
limit?: number;
sortBy?: string;
sortOrder?: 'asc' | 'desc';
}
Validation Strategy Interfaces
ValidationStrategyConfig
Configuration for validation strategies.
interface ValidationStrategyConfig {
strategy: string;
provider: Provider;
enabled: boolean;
options?: Record<string, any>;
}
TenantValidationResult
Result of tenant validation.
interface TenantValidationResult {
isValid: boolean;
tenant?: ITenant;
error?: string;
metadata?: Record<string, any>;
}
Utility Type Guards
isTypeOrmConnection
Type guard for TypeORM connections.
function isTypeOrmConnection(
connection: IOrmConnection,
): connection is ITypeOrmConnection {
return connection.type === 'typeorm';
}
isDrizzleConnection
Type guard for Drizzle connections.
function isDrizzleConnection(
connection: IOrmConnection,
): connection is IDrizzleConnection {
return connection.type === 'drizzle';
}
Example Usage
Using Type Guards
@Injectable()
export class ConnectionService {
async performOperation(connection: IOrmConnection) {
if (isDrizzleConnection(connection)) {
const db = connection.getDatabase(); // NodePgDatabase
await db.select().from(tasks);
}
if (isTypeOrmConnection(connection)) {
const dataSource = connection.getDatabase(); // DataSource
const repo = dataSource.getRepository(Task);
await repo.find();
}
}
}
Configuration Usage
const config: MultiTenantModuleOptions = {
database: {
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'password',
database: 'multitenant_db',
},
orm: {
type: 'drizzle', // or 'typeorm'
drizzle: {
schema: { users, tasks },
logger: true,
},
},
platform: 'express',
autoCreateSchemas: true,
tenantResolution: {
strategy: 'header',
headerName: 'x-tenant-id',
},
};
Migration Between Interfaces
When migrating from TypeORM to Drizzle:
// Before (TypeORM)
interface IConnection {
getDataSource(): DataSource;
}
// After (Drizzle - with type safety)
const connection: IDrizzleConnection = ...;
const db = connection.getDatabase(); // Fully typed NodePgDatabase
Best Practices
For Type Safety
- Use Type Guards: Always use type guards before ORM-specific operations
- Leverage Generics: Use TypeScript generics for flexible, type-safe code
- Validate Configuration: Ensure configuration interfaces match your ORM choice
For Flexibility
- ORM-Agnostic Design: Design services to work with
IOrmConnectionwhen possible - Conditional Logic: Use type guards for ORM-specific optimizations
- Configuration Validation: Validate
OrmConfigbefore module initialization
For Maintenance
- Interface Documentation: Keep interface documentation updated
- Version Compatibility: Track interface changes between versions
- Type Migration: Use migration guides when updating interfaces