drizzle-multitenant 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,6 +56,15 @@ export default defineConfig({
56
56
  tenant: tenantSchema,
57
57
  shared: sharedSchema,
58
58
  },
59
+ // Optional: CLI migrations config
60
+ migrations: {
61
+ tenantFolder: './drizzle/tenant',
62
+ migrationsTable: '__drizzle_migrations', // Custom table name
63
+ tenantDiscovery: async () => {
64
+ // Return list of tenant IDs for migrations
65
+ return ['tenant-1', 'tenant-2'];
66
+ },
67
+ },
59
68
  });
60
69
  ```
61
70
 
package/dist/cli/index.js CHANGED
@@ -556,6 +556,7 @@ async function loadConfig(configPath) {
556
556
  return {
557
557
  config: exported,
558
558
  migrationsFolder: exported.migrations?.tenantFolder,
559
+ migrationsTable: exported.migrations?.migrationsTable,
559
560
  tenantDiscovery: exported.migrations?.tenantDiscovery
560
561
  };
561
562
  }
@@ -587,7 +588,7 @@ var migrateCommand = new Command("migrate").description("Apply pending migration
587
588
  const spinner = createSpinner("Loading configuration...");
588
589
  try {
589
590
  spinner.start();
590
- const { config, migrationsFolder, tenantDiscovery } = await loadConfig(options.config);
591
+ const { config, migrationsFolder, migrationsTable, tenantDiscovery } = await loadConfig(options.config);
591
592
  const folder = options.migrationsFolder ? resolveMigrationsFolder(options.migrationsFolder) : resolveMigrationsFolder(migrationsFolder);
592
593
  let discoveryFn;
593
594
  if (options.tenant) {
@@ -614,6 +615,7 @@ var migrateCommand = new Command("migrate").description("Apply pending migration
614
615
  spinner.text = "Discovering tenants...";
615
616
  const migrator = createMigrator(config, {
616
617
  migrationsFolder: folder,
618
+ migrationsTable,
617
619
  tenantDiscovery: discoveryFn
618
620
  });
619
621
  const tenantIds = await discoveryFn();
@@ -674,7 +676,7 @@ var statusCommand = new Command("status").description("Show migration status for
674
676
  const spinner = createSpinner("Loading configuration...");
675
677
  try {
676
678
  spinner.start();
677
- const { config, migrationsFolder, tenantDiscovery } = await loadConfig(options.config);
679
+ const { config, migrationsFolder, migrationsTable, tenantDiscovery } = await loadConfig(options.config);
678
680
  if (!tenantDiscovery) {
679
681
  throw new Error(
680
682
  "No tenant discovery function configured. Add migrations.tenantDiscovery to your config."
@@ -684,6 +686,7 @@ var statusCommand = new Command("status").description("Show migration status for
684
686
  spinner.text = "Discovering tenants...";
685
687
  const migrator = createMigrator(config, {
686
688
  migrationsFolder: folder,
689
+ migrationsTable,
687
690
  tenantDiscovery
688
691
  });
689
692
  spinner.text = "Fetching migration status...";
@@ -752,10 +755,11 @@ var tenantCreateCommand = new Command("tenant:create").description("Create a new
752
755
  const spinner = createSpinner("Loading configuration...");
753
756
  try {
754
757
  spinner.start();
755
- const { config, migrationsFolder } = await loadConfig(options.config);
758
+ const { config, migrationsFolder, migrationsTable } = await loadConfig(options.config);
756
759
  const folder = options.migrationsFolder ? resolveMigrationsFolder(options.migrationsFolder) : resolveMigrationsFolder(migrationsFolder);
757
760
  const migrator = createMigrator(config, {
758
761
  migrationsFolder: folder,
762
+ migrationsTable,
759
763
  tenantDiscovery: async () => []
760
764
  });
761
765
  const schemaName = config.isolation.schemaNameTemplate(options.id);
@@ -800,10 +804,11 @@ var tenantDropCommand = new Command("tenant:drop").description("Drop a tenant sc
800
804
  const spinner = createSpinner("Loading configuration...");
801
805
  try {
802
806
  spinner.start();
803
- const { config, migrationsFolder } = await loadConfig(options.config);
807
+ const { config, migrationsFolder, migrationsTable } = await loadConfig(options.config);
804
808
  const folder = options.migrationsFolder ? resolveMigrationsFolder(options.migrationsFolder) : resolveMigrationsFolder(migrationsFolder);
805
809
  const migrator = createMigrator(config, {
806
810
  migrationsFolder: folder,
811
+ migrationsTable,
807
812
  tenantDiscovery: async () => []
808
813
  });
809
814
  const schemaName = config.isolation.schemaNameTemplate(options.id);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/migrator/migrator.ts","../../src/cli/utils/spinner.ts","../../src/cli/utils/table.ts","../../src/cli/utils/config.ts","../../src/cli/commands/migrate.ts","../../src/cli/commands/status.ts","../../src/cli/commands/generate.ts","../../src/cli/commands/tenant-create.ts","../../src/cli/commands/tenant-drop.ts","../../src/cli/index.ts"],"names":["error","chalk","tenantIds","Command","resolve","existsSync","readdir","join"],"mappings":"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","file":"index.js","sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { Pool } from 'pg';\nimport type { Config } from '../types.js';\nimport type {\n MigratorConfig,\n MigrationFile,\n MigrateOptions,\n TenantMigrationResult,\n MigrationResults,\n TenantMigrationStatus,\n AppliedMigration,\n CreateTenantOptions,\n DropTenantOptions,\n} from './types.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Parallel migration engine for multi-tenant applications\n */\nexport class Migrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n\n constructor(\n private readonly tenantConfig: Config<TTenantSchema, TSharedSchema>,\n private readonly migratorConfig: MigratorConfig\n ) {\n this.migrationsTable = migratorConfig.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Migrate all tenants in parallel\n */\n async migrateAll(options: MigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n dryRun = false,\n } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Migrate a single tenant\n */\n async migrateTenant(\n tenantId: string,\n migrations?: MigrationFile[],\n options: { dryRun?: boolean; onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const appliedMigrations: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n await this.migratorConfig.hooks?.beforeTenant?.(tenantId);\n\n // Ensure migrations table exists\n await this.ensureMigrationsTable(pool, schemaName);\n\n // Load migrations if not provided\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Get applied migrations\n const applied = await this.getAppliedMigrations(pool, schemaName);\n const appliedSet = new Set(applied.map((m) => m.name));\n\n // Filter pending migrations\n const pending = allMigrations.filter((m) => !appliedSet.has(m.name));\n\n if (options.dryRun) {\n return {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: pending.map((m) => m.name),\n durationMs: Date.now() - startTime,\n };\n }\n\n // Apply pending migrations\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.migratorConfig.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.applyMigration(pool, schemaName, migration);\n await this.migratorConfig.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n appliedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Migrate specific tenants\n */\n async migrateTenants(tenantIds: string[], options: MigrateOptions = {}): Promise<MigrationResults> {\n const migrations = await this.loadMigrations();\n const results: TenantMigrationResult[] = [];\n\n const { concurrency = 10, onProgress, onError } = options;\n\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun: options.dryRun ?? false, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n onError?.(tenantId, error as Error);\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Get migration status for all tenants\n */\n async getStatus(): Promise<TenantMigrationStatus[]> {\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n const statuses: TenantMigrationStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.getTenantStatus(tenantId, migrations));\n }\n\n return statuses;\n }\n\n /**\n * Get migration status for a specific tenant\n */\n async getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const pool = await this.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Check if migrations table exists\n const tableExists = await this.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: allMigrations.length,\n pendingMigrations: allMigrations.map((m) => m.name),\n status: allMigrations.length > 0 ? 'behind' : 'ok',\n };\n }\n\n const applied = await this.getAppliedMigrations(pool, schemaName);\n const appliedSet = new Set(applied.map((m) => m.name));\n const pending = allMigrations.filter((m) => !appliedSet.has(m.name));\n\n return {\n tenantId,\n schemaName,\n appliedCount: applied.length,\n pendingCount: pending.length,\n pendingMigrations: pending.map((m) => m.name),\n status: pending.length > 0 ? 'behind' : 'ok',\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: 0,\n pendingMigrations: [],\n status: 'error',\n error: (error as Error).message,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Create a new tenant schema and optionally apply migrations\n */\n async createTenant(tenantId: string, options: CreateTenantOptions = {}): Promise<void> {\n const { migrate = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n // Create schema\n await pool.query(`CREATE SCHEMA IF NOT EXISTS \"${schemaName}\"`);\n\n if (migrate) {\n // Apply all migrations\n await this.migrateTenant(tenantId);\n }\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Drop a tenant schema\n */\n async dropTenant(tenantId: string, options: DropTenantOptions = {}): Promise<void> {\n const { cascade = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const cascadeSql = cascade ? 'CASCADE' : 'RESTRICT';\n await pool.query(`DROP SCHEMA IF EXISTS \"${schemaName}\" ${cascadeSql}`);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Check if a tenant schema exists\n */\n async tenantExists(tenantId: string): Promise<boolean> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.schemata WHERE schema_name = $1`,\n [schemaName]\n );\n return result.rowCount !== null && result.rowCount > 0;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Load migration files from the migrations folder\n */\n private async loadMigrations(): Promise<MigrationFile[]> {\n const files = await readdir(this.migratorConfig.migrationsFolder);\n\n const migrations: MigrationFile[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.sql')) continue;\n\n const filePath = join(this.migratorConfig.migrationsFolder, file);\n const content = await readFile(filePath, 'utf-8');\n\n // Extract timestamp from filename (e.g., 0001_migration_name.sql)\n const match = file.match(/^(\\d+)_/);\n const timestamp = match?.[1] ? parseInt(match[1], 10) : 0;\n\n migrations.push({\n name: basename(file, '.sql'),\n path: filePath,\n sql: content,\n timestamp,\n });\n }\n\n // Sort by timestamp\n return migrations.sort((a, b) => a.timestamp - b.timestamp);\n }\n\n /**\n * Create a pool for a specific schema\n */\n private async createPool(schemaName: string): Promise<Pool> {\n return new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n options: `-c search_path=\"${schemaName}\",public`,\n });\n }\n\n /**\n * Ensure migrations table exists\n */\n private async ensureMigrationsTable(pool: Pool, schemaName: string): Promise<void> {\n await pool.query(`\n CREATE TABLE IF NOT EXISTS \"${schemaName}\".\"${this.migrationsTable}\" (\n id SERIAL PRIMARY KEY,\n name VARCHAR(255) NOT NULL UNIQUE,\n applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n )\n `);\n }\n\n /**\n * Check if migrations table exists\n */\n private async migrationsTableExists(pool: Pool, schemaName: string): Promise<boolean> {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, this.migrationsTable]\n );\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Get applied migrations for a schema\n */\n private async getAppliedMigrations(pool: Pool, schemaName: string): Promise<AppliedMigration[]> {\n const result = await pool.query<{ id: number; name: string; applied_at: Date }>(\n `SELECT id, name, applied_at FROM \"${schemaName}\".\"${this.migrationsTable}\" ORDER BY id`\n );\n return result.rows.map((row) => ({\n id: row.id,\n name: row.name,\n appliedAt: row.applied_at,\n }));\n }\n\n /**\n * Apply a migration to a schema\n */\n private async applyMigration(pool: Pool, schemaName: string, migration: MigrationFile): Promise<void> {\n const client = await pool.connect();\n\n try {\n await client.query('BEGIN');\n\n // Execute migration SQL\n await client.query(migration.sql);\n\n // Record migration\n await client.query(\n `INSERT INTO \"${schemaName}\".\"${this.migrationsTable}\" (name) VALUES ($1)`,\n [migration.name]\n );\n\n await client.query('COMMIT');\n } catch (error) {\n await client.query('ROLLBACK');\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Create a skipped result\n */\n private createSkippedResult(tenantId: string): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error result\n */\n private createErrorResult(tenantId: string, error: Error): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate migration results\n */\n private aggregateResults(results: TenantMigrationResult[]): MigrationResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success && r.error !== 'Skipped due to abort').length,\n skipped: results.filter((r) => r.error === 'Skipped due to abort').length,\n details: results,\n };\n }\n}\n\n/**\n * Create a migrator instance\n */\nexport function createMigrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantConfig: Config<TTenantSchema, TSharedSchema>,\n migratorConfig: MigratorConfig\n): Migrator<TTenantSchema, TSharedSchema> {\n return new Migrator(tenantConfig, migratorConfig);\n}\n","import ora, { type Ora } from 'ora';\nimport chalk from 'chalk';\n\n/**\n * Create a spinner instance\n */\nexport function createSpinner(text: string): Ora {\n return ora({\n text,\n color: 'cyan',\n });\n}\n\n/**\n * Format success message\n */\nexport function success(message: string): string {\n return chalk.green('✓ ') + message;\n}\n\n/**\n * Format error message\n */\nexport function error(message: string): string {\n return chalk.red('✗ ') + message;\n}\n\n/**\n * Format warning message\n */\nexport function warning(message: string): string {\n return chalk.yellow('⚠ ') + message;\n}\n\n/**\n * Format info message\n */\nexport function info(message: string): string {\n return chalk.blue('ℹ ') + message;\n}\n\n/**\n * Format dim text\n */\nexport function dim(message: string): string {\n return chalk.dim(message);\n}\n\n/**\n * Format bold text\n */\nexport function bold(message: string): string {\n return chalk.bold(message);\n}\n\n/**\n * Format cyan text\n */\nexport function cyan(message: string): string {\n return chalk.cyan(message);\n}\n\n/**\n * Format green text\n */\nexport function green(message: string): string {\n return chalk.green(message);\n}\n\n/**\n * Format red text\n */\nexport function red(message: string): string {\n return chalk.red(message);\n}\n\n/**\n * Format yellow text\n */\nexport function yellow(message: string): string {\n return chalk.yellow(message);\n}\n","import Table from 'cli-table3';\nimport chalk from 'chalk';\nimport type { TenantMigrationStatus } from '../../migrator/types.js';\n\n/**\n * Create a status table for tenant migrations\n */\nexport function createStatusTable(statuses: TenantMigrationStatus[]): string {\n const table = new Table({\n head: [\n chalk.cyan('Tenant'),\n chalk.cyan('Schema'),\n chalk.cyan('Applied'),\n chalk.cyan('Pending'),\n chalk.cyan('Status'),\n ],\n style: {\n head: [],\n border: [],\n },\n });\n\n for (const status of statuses) {\n const statusIcon = getStatusIcon(status.status);\n const statusText = getStatusText(status.status);\n\n table.push([\n status.tenantId,\n chalk.dim(status.schemaName),\n chalk.green(status.appliedCount.toString()),\n status.pendingCount > 0\n ? chalk.yellow(status.pendingCount.toString())\n : chalk.dim('0'),\n `${statusIcon} ${statusText}`,\n ]);\n }\n\n return table.toString();\n}\n\n/**\n * Create a results table for migration execution\n */\nexport function createResultsTable(\n results: Array<{\n tenantId: string;\n schemaName: string;\n success: boolean;\n appliedMigrations: string[];\n error?: string;\n durationMs: number;\n }>\n): string {\n const table = new Table({\n head: [\n chalk.cyan('Tenant'),\n chalk.cyan('Migrations'),\n chalk.cyan('Duration'),\n chalk.cyan('Status'),\n ],\n style: {\n head: [],\n border: [],\n },\n });\n\n for (const result of results) {\n const statusIcon = result.success ? chalk.green('✓') : chalk.red('✗');\n const statusText = result.success\n ? chalk.green('OK')\n : chalk.red(result.error ?? 'Failed');\n\n table.push([\n result.tenantId,\n result.appliedMigrations.length.toString(),\n `${result.durationMs}ms`,\n `${statusIcon} ${statusText}`,\n ]);\n }\n\n return table.toString();\n}\n\n/**\n * Create a pending migrations summary\n */\nexport function createPendingSummary(statuses: TenantMigrationStatus[]): string {\n const pendingMap = new Map<string, number>();\n\n for (const status of statuses) {\n for (const migration of status.pendingMigrations) {\n pendingMap.set(migration, (pendingMap.get(migration) || 0) + 1);\n }\n }\n\n if (pendingMap.size === 0) {\n return chalk.green('\\nAll tenants are up to date.');\n }\n\n const lines = [chalk.yellow('\\nPending migrations:')];\n\n for (const [migration, count] of pendingMap.entries()) {\n lines.push(\n ` ${chalk.dim('-')} ${migration} ${chalk.dim(`(${count} tenant${count > 1 ? 's' : ''})`)}`\n );\n }\n\n lines.push(\n chalk.dim('\\nRun \\'drizzle-multitenant migrate --all\\' to apply pending migrations.')\n );\n\n return lines.join('\\n');\n}\n\n/**\n * Get status icon\n */\nfunction getStatusIcon(status: 'ok' | 'behind' | 'error'): string {\n switch (status) {\n case 'ok':\n return chalk.green('✓');\n case 'behind':\n return chalk.yellow('⚠');\n case 'error':\n return chalk.red('✗');\n }\n}\n\n/**\n * Get status text\n */\nfunction getStatusText(status: 'ok' | 'behind' | 'error'): string {\n switch (status) {\n case 'ok':\n return chalk.green('OK');\n case 'behind':\n return chalk.yellow('Behind');\n case 'error':\n return chalk.red('Error');\n }\n}\n","import { pathToFileURL } from 'node:url';\nimport { resolve, extname } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { Config } from '../../types.js';\n\nconst CONFIG_FILE_NAMES = [\n 'tenant.config.ts',\n 'tenant.config.js',\n 'tenant.config.mjs',\n 'drizzle-multitenant.config.ts',\n 'drizzle-multitenant.config.js',\n 'drizzle-multitenant.config.mjs',\n];\n\nexport interface LoadedConfig {\n config: Config<Record<string, unknown>, Record<string, unknown>>;\n migrationsFolder?: string;\n tenantDiscovery?: () => Promise<string[]>;\n}\n\n/**\n * Load configuration from file\n */\nexport async function loadConfig(configPath?: string): Promise<LoadedConfig> {\n const cwd = process.cwd();\n\n let configFile: string | undefined;\n\n if (configPath) {\n configFile = resolve(cwd, configPath);\n if (!existsSync(configFile)) {\n throw new Error(`Config file not found: ${configFile}`);\n }\n } else {\n // Search for config file\n for (const name of CONFIG_FILE_NAMES) {\n const path = resolve(cwd, name);\n if (existsSync(path)) {\n configFile = path;\n break;\n }\n }\n }\n\n if (!configFile) {\n throw new Error(\n 'Config file not found. Create a tenant.config.ts or use --config flag.'\n );\n }\n\n // Handle TypeScript files\n const ext = extname(configFile);\n if (ext === '.ts') {\n // Register ts-node or tsx for TypeScript support\n await registerTypeScript();\n }\n\n // Import the config\n const configUrl = pathToFileURL(configFile).href;\n const module = await import(configUrl);\n const exported = module.default ?? module;\n\n if (!exported.connection || !exported.isolation || !exported.schemas) {\n throw new Error(\n 'Invalid config file. Expected an object with connection, isolation, and schemas properties.'\n );\n }\n\n return {\n config: exported,\n migrationsFolder: exported.migrations?.tenantFolder,\n tenantDiscovery: exported.migrations?.tenantDiscovery,\n };\n}\n\n/**\n * Register TypeScript loader\n */\nasync function registerTypeScript(): Promise<void> {\n try {\n // Try tsx first (faster)\n await import('tsx/esm');\n } catch {\n try {\n // Fall back to ts-node\n await import('ts-node/esm');\n } catch {\n throw new Error(\n 'TypeScript config requires tsx or ts-node. Install with: npm install -D tsx'\n );\n }\n }\n}\n\n/**\n * Resolve migrations folder path\n */\nexport function resolveMigrationsFolder(folder?: string): string {\n const cwd = process.cwd();\n const defaultFolder = './drizzle/tenant';\n\n const resolved = resolve(cwd, folder ?? defaultFolder);\n\n if (!existsSync(resolved)) {\n throw new Error(`Migrations folder not found: ${resolved}`);\n }\n\n return resolved;\n}\n","import { Command } from 'commander';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n createResultsTable,\n success,\n error,\n info,\n warning,\n bold,\n dim,\n} from '../utils/index.js';\n\nexport const migrateCommand = new Command('migrate')\n .description('Apply pending migrations to tenant schemas')\n .option('-c, --config <path>', 'Path to config file')\n .option('-a, --all', 'Migrate all tenants')\n .option('-t, --tenant <id>', 'Migrate a specific tenant')\n .option('--tenants <ids>', 'Migrate specific tenants (comma-separated)')\n .option('--concurrency <number>', 'Number of concurrent migrations', '10')\n .option('--dry-run', 'Show what would be applied without executing')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder, tenantDiscovery } = await loadConfig(options.config);\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n // Determine tenant discovery function\n let discoveryFn: () => Promise<string[]>;\n\n if (options.tenant) {\n discoveryFn = async () => [options.tenant];\n } else if (options.tenants) {\n const tenantIds = options.tenants.split(',').map((id: string) => id.trim());\n discoveryFn = async () => tenantIds;\n } else if (options.all) {\n if (!tenantDiscovery) {\n throw new Error(\n 'No tenant discovery function configured. Add migrations.tenantDiscovery to your config.'\n );\n }\n discoveryFn = tenantDiscovery;\n } else {\n spinner.stop();\n console.log(error('Please specify --all, --tenant, or --tenants'));\n console.log(dim('\\nExamples:'));\n console.log(dim(' npx drizzle-multitenant migrate --all'));\n console.log(dim(' npx drizzle-multitenant migrate --tenant=tenant-uuid'));\n console.log(dim(' npx drizzle-multitenant migrate --tenants=tenant-1,tenant-2'));\n process.exit(1);\n }\n\n spinner.text = 'Discovering tenants...';\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n tenantDiscovery: discoveryFn,\n });\n\n const tenantIds = await discoveryFn();\n\n if (tenantIds.length === 0) {\n spinner.stop();\n console.log(warning('No tenants found.'));\n return;\n }\n\n spinner.text = `Found ${tenantIds.length} tenant${tenantIds.length > 1 ? 's' : ''}`;\n spinner.succeed();\n\n if (options.dryRun) {\n console.log(info(bold('\\nDry run mode - no changes will be made\\n')));\n }\n\n console.log(info(`Migrating ${tenantIds.length} tenant${tenantIds.length > 1 ? 's' : ''}...\\n`));\n\n const concurrency = parseInt(options.concurrency, 10);\n let completed = 0;\n\n const results = await migrator.migrateAll({\n concurrency,\n dryRun: options.dryRun,\n onProgress: (tenantId, status, migrationName) => {\n if (status === 'completed') {\n completed++;\n const progress = `[${completed}/${tenantIds.length}]`;\n console.log(`${dim(progress)} ${success(tenantId)}`);\n } else if (status === 'failed') {\n completed++;\n const progress = `[${completed}/${tenantIds.length}]`;\n console.log(`${dim(progress)} ${error(tenantId)}`);\n } else if (status === 'migrating' && migrationName) {\n // Optional: show individual migration progress\n }\n },\n onError: (tenantId, err) => {\n console.log(error(`${tenantId}: ${err.message}`));\n return 'continue';\n },\n });\n\n console.log('\\n' + bold('Results:'));\n console.log(createResultsTable(results.details));\n\n console.log('\\n' + bold('Summary:'));\n console.log(` Total: ${results.total}`);\n console.log(` Succeeded: ${success(results.succeeded.toString())}`);\n if (results.failed > 0) {\n console.log(` Failed: ${error(results.failed.toString())}`);\n }\n if (results.skipped > 0) {\n console.log(` Skipped: ${warning(results.skipped.toString())}`);\n }\n\n if (results.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n createStatusTable,\n createPendingSummary,\n error,\n bold,\n} from '../utils/index.js';\n\nexport const statusCommand = new Command('status')\n .description('Show migration status for all tenants')\n .option('-c, --config <path>', 'Path to config file')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder, tenantDiscovery } = await loadConfig(options.config);\n\n if (!tenantDiscovery) {\n throw new Error(\n 'No tenant discovery function configured. Add migrations.tenantDiscovery to your config.'\n );\n }\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n spinner.text = 'Discovering tenants...';\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n tenantDiscovery,\n });\n\n spinner.text = 'Fetching migration status...';\n\n const statuses = await migrator.getStatus();\n\n spinner.succeed(`Found ${statuses.length} tenant${statuses.length > 1 ? 's' : ''}`);\n\n console.log('\\n' + bold('Migration Status:'));\n console.log(createStatusTable(statuses));\n console.log(createPendingSummary(statuses));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { writeFile, mkdir, readdir } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport {\n loadConfig,\n createSpinner,\n success,\n error,\n dim,\n} from '../utils/index.js';\n\nexport const generateCommand = new Command('generate')\n .description('Generate a new migration file')\n .requiredOption('-n, --name <name>', 'Migration name')\n .option('-c, --config <path>', 'Path to config file')\n .option('--type <type>', 'Migration type: tenant or shared', 'tenant')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { migrationsFolder: configFolder } = await loadConfig(options.config);\n\n const cwd = process.cwd();\n let folder: string;\n\n if (options.migrationsFolder) {\n folder = resolve(cwd, options.migrationsFolder);\n } else if (configFolder) {\n folder = resolve(cwd, configFolder);\n } else {\n folder = resolve(cwd, options.type === 'shared' ? './drizzle/shared' : './drizzle/tenant');\n }\n\n // Ensure folder exists\n if (!existsSync(folder)) {\n await mkdir(folder, { recursive: true });\n spinner.text = `Created migrations folder: ${folder}`;\n }\n\n spinner.text = 'Generating migration...';\n\n // Get next sequence number\n const files = existsSync(folder) ? await readdir(folder) : [];\n const sqlFiles = files.filter((f) => f.endsWith('.sql'));\n\n let maxSequence = 0;\n for (const file of sqlFiles) {\n const match = file.match(/^(\\d+)_/);\n if (match) {\n const seq = parseInt(match[1], 10);\n if (seq > maxSequence) {\n maxSequence = seq;\n }\n }\n }\n\n const nextSequence = (maxSequence + 1).toString().padStart(4, '0');\n const safeName = options.name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_|_$/g, '');\n\n const fileName = `${nextSequence}_${safeName}.sql`;\n const filePath = join(folder, fileName);\n\n // Create migration file with template\n const template = `-- Migration: ${options.name}\n-- Created at: ${new Date().toISOString()}\n-- Type: ${options.type}\n\n-- Write your SQL migration here\n\n`;\n\n await writeFile(filePath, template, 'utf-8');\n\n spinner.succeed('Migration generated');\n\n console.log('\\n' + success(`Created: ${dim(filePath)}`));\n console.log(dim('\\nEdit this file to add your migration SQL.'));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n success,\n error,\n warning,\n dim,\n} from '../utils/index.js';\n\nexport const tenantCreateCommand = new Command('tenant:create')\n .description('Create a new tenant schema and apply all migrations')\n .requiredOption('--id <tenantId>', 'Tenant ID')\n .option('-c, --config <path>', 'Path to config file')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .option('--no-migrate', 'Skip applying migrations after creating schema')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder } = await loadConfig(options.config);\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n tenantDiscovery: async () => [],\n });\n\n const schemaName = config.isolation.schemaNameTemplate(options.id);\n\n spinner.text = `Checking if tenant ${options.id} exists...`;\n\n const exists = await migrator.tenantExists(options.id);\n if (exists) {\n spinner.warn(`Tenant ${options.id} already exists (${schemaName})`);\n\n if (options.migrate) {\n spinner.start();\n spinner.text = 'Applying pending migrations...';\n\n const result = await migrator.migrateTenant(options.id);\n\n if (result.appliedMigrations.length > 0) {\n spinner.succeed(`Applied ${result.appliedMigrations.length} migration(s)`);\n for (const migration of result.appliedMigrations) {\n console.log(` ${dim('-')} ${migration}`);\n }\n } else {\n spinner.succeed('No pending migrations');\n }\n }\n\n return;\n }\n\n spinner.text = `Creating tenant schema ${schemaName}...`;\n\n await migrator.createTenant(options.id, {\n migrate: options.migrate,\n });\n\n spinner.succeed(`Tenant ${options.id} created`);\n\n console.log('\\n' + success('Schema created: ') + dim(schemaName));\n\n if (options.migrate) {\n console.log(success('All migrations applied'));\n } else {\n console.log(warning('Migrations skipped. Run migrate to apply.'));\n }\n\n console.log(dim('\\nYou can now use this tenant:'));\n console.log(dim(` const db = tenants.getDb('${options.id}');`));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createInterface } from 'node:readline';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n success,\n error,\n warning,\n dim,\n red,\n bold,\n} from '../utils/index.js';\n\nexport const tenantDropCommand = new Command('tenant:drop')\n .description('Drop a tenant schema (DESTRUCTIVE)')\n .requiredOption('--id <tenantId>', 'Tenant ID')\n .option('-c, --config <path>', 'Path to config file')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .option('-f, --force', 'Skip confirmation prompt')\n .option('--no-cascade', 'Use RESTRICT instead of CASCADE')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder } = await loadConfig(options.config);\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n tenantDiscovery: async () => [],\n });\n\n const schemaName = config.isolation.schemaNameTemplate(options.id);\n\n spinner.text = `Checking if tenant ${options.id} exists...`;\n\n const exists = await migrator.tenantExists(options.id);\n if (!exists) {\n spinner.warn(`Tenant ${options.id} does not exist`);\n return;\n }\n\n spinner.stop();\n\n // Confirmation prompt\n if (!options.force) {\n console.log(red(bold('\\n⚠️ WARNING: This action is DESTRUCTIVE and IRREVERSIBLE!')));\n console.log(dim(`\\nYou are about to drop schema: ${schemaName}`));\n console.log(dim('All tables and data in this schema will be permanently deleted.\\n'));\n\n const confirmed = await askConfirmation(\n `Type \"${options.id}\" to confirm deletion: `,\n options.id\n );\n\n if (!confirmed) {\n console.log('\\n' + warning('Operation cancelled.'));\n return;\n }\n }\n\n spinner.start();\n spinner.text = `Dropping tenant schema ${schemaName}...`;\n\n await migrator.dropTenant(options.id, {\n cascade: options.cascade,\n });\n\n spinner.succeed(`Tenant ${options.id} dropped`);\n\n console.log('\\n' + success('Schema deleted: ') + dim(schemaName));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n\n/**\n * Ask for confirmation\n */\nasync function askConfirmation(question: string, expected: string): Promise<boolean> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim() === expected);\n });\n });\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport {\n migrateCommand,\n statusCommand,\n generateCommand,\n tenantCreateCommand,\n tenantDropCommand,\n} from './commands/index.js';\n\nconst program = new Command();\n\nprogram\n .name('drizzle-multitenant')\n .description('Multi-tenancy toolkit for Drizzle ORM')\n .version('0.3.0');\n\n// Register commands\nprogram.addCommand(migrateCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(generateCommand);\nprogram.addCommand(tenantCreateCommand);\nprogram.addCommand(tenantDropCommand);\n\n// Parse arguments\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../../src/migrator/migrator.ts","../../src/cli/utils/spinner.ts","../../src/cli/utils/table.ts","../../src/cli/utils/config.ts","../../src/cli/commands/migrate.ts","../../src/cli/commands/status.ts","../../src/cli/commands/generate.ts","../../src/cli/commands/tenant-create.ts","../../src/cli/commands/tenant-drop.ts","../../src/cli/index.ts"],"names":["error","chalk","tenantIds","Command","resolve","existsSync","readdir","join"],"mappings":"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","file":"index.js","sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { join, basename } from 'node:path';\nimport { Pool } from 'pg';\nimport type { Config } from '../types.js';\nimport type {\n MigratorConfig,\n MigrationFile,\n MigrateOptions,\n TenantMigrationResult,\n MigrationResults,\n TenantMigrationStatus,\n AppliedMigration,\n CreateTenantOptions,\n DropTenantOptions,\n} from './types.js';\n\nconst DEFAULT_MIGRATIONS_TABLE = '__drizzle_migrations';\n\n/**\n * Parallel migration engine for multi-tenant applications\n */\nexport class Migrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n> {\n private readonly migrationsTable: string;\n\n constructor(\n private readonly tenantConfig: Config<TTenantSchema, TSharedSchema>,\n private readonly migratorConfig: MigratorConfig\n ) {\n this.migrationsTable = migratorConfig.migrationsTable ?? DEFAULT_MIGRATIONS_TABLE;\n }\n\n /**\n * Migrate all tenants in parallel\n */\n async migrateAll(options: MigrateOptions = {}): Promise<MigrationResults> {\n const {\n concurrency = 10,\n onProgress,\n onError,\n dryRun = false,\n } = options;\n\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n\n const results: TenantMigrationResult[] = [];\n let aborted = false;\n\n // Process tenants in batches\n for (let i = 0; i < tenantIds.length && !aborted; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n if (aborted) {\n return this.createSkippedResult(tenantId);\n }\n\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n const action = onError?.(tenantId, error as Error);\n if (action === 'abort') {\n aborted = true;\n }\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n // Mark remaining tenants as skipped if aborted\n if (aborted) {\n const remaining = tenantIds.slice(results.length);\n for (const tenantId of remaining) {\n results.push(this.createSkippedResult(tenantId));\n }\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Migrate a single tenant\n */\n async migrateTenant(\n tenantId: string,\n migrations?: MigrationFile[],\n options: { dryRun?: boolean; onProgress?: MigrateOptions['onProgress'] } = {}\n ): Promise<TenantMigrationResult> {\n const startTime = Date.now();\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const appliedMigrations: string[] = [];\n\n const pool = await this.createPool(schemaName);\n\n try {\n await this.migratorConfig.hooks?.beforeTenant?.(tenantId);\n\n // Ensure migrations table exists\n await this.ensureMigrationsTable(pool, schemaName);\n\n // Load migrations if not provided\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Get applied migrations\n const applied = await this.getAppliedMigrations(pool, schemaName);\n const appliedSet = new Set(applied.map((m) => m.name));\n\n // Filter pending migrations\n const pending = allMigrations.filter((m) => !appliedSet.has(m.name));\n\n if (options.dryRun) {\n return {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations: pending.map((m) => m.name),\n durationMs: Date.now() - startTime,\n };\n }\n\n // Apply pending migrations\n for (const migration of pending) {\n const migrationStart = Date.now();\n options.onProgress?.(tenantId, 'migrating', migration.name);\n\n await this.migratorConfig.hooks?.beforeMigration?.(tenantId, migration.name);\n await this.applyMigration(pool, schemaName, migration);\n await this.migratorConfig.hooks?.afterMigration?.(\n tenantId,\n migration.name,\n Date.now() - migrationStart\n );\n\n appliedMigrations.push(migration.name);\n }\n\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: true,\n appliedMigrations,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } catch (error) {\n const result: TenantMigrationResult = {\n tenantId,\n schemaName,\n success: false,\n appliedMigrations,\n error: (error as Error).message,\n durationMs: Date.now() - startTime,\n };\n\n await this.migratorConfig.hooks?.afterTenant?.(tenantId, result);\n\n return result;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Migrate specific tenants\n */\n async migrateTenants(tenantIds: string[], options: MigrateOptions = {}): Promise<MigrationResults> {\n const migrations = await this.loadMigrations();\n const results: TenantMigrationResult[] = [];\n\n const { concurrency = 10, onProgress, onError } = options;\n\n for (let i = 0; i < tenantIds.length; i += concurrency) {\n const batch = tenantIds.slice(i, i + concurrency);\n\n const batchResults = await Promise.all(\n batch.map(async (tenantId) => {\n try {\n onProgress?.(tenantId, 'starting');\n const result = await this.migrateTenant(tenantId, migrations, { dryRun: options.dryRun ?? false, onProgress });\n onProgress?.(tenantId, result.success ? 'completed' : 'failed');\n return result;\n } catch (error) {\n onProgress?.(tenantId, 'failed');\n onError?.(tenantId, error as Error);\n return this.createErrorResult(tenantId, error as Error);\n }\n })\n );\n\n results.push(...batchResults);\n }\n\n return this.aggregateResults(results);\n }\n\n /**\n * Get migration status for all tenants\n */\n async getStatus(): Promise<TenantMigrationStatus[]> {\n const tenantIds = await this.migratorConfig.tenantDiscovery();\n const migrations = await this.loadMigrations();\n const statuses: TenantMigrationStatus[] = [];\n\n for (const tenantId of tenantIds) {\n statuses.push(await this.getTenantStatus(tenantId, migrations));\n }\n\n return statuses;\n }\n\n /**\n * Get migration status for a specific tenant\n */\n async getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n const pool = await this.createPool(schemaName);\n\n try {\n const allMigrations = migrations ?? await this.loadMigrations();\n\n // Check if migrations table exists\n const tableExists = await this.migrationsTableExists(pool, schemaName);\n if (!tableExists) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: allMigrations.length,\n pendingMigrations: allMigrations.map((m) => m.name),\n status: allMigrations.length > 0 ? 'behind' : 'ok',\n };\n }\n\n const applied = await this.getAppliedMigrations(pool, schemaName);\n const appliedSet = new Set(applied.map((m) => m.name));\n const pending = allMigrations.filter((m) => !appliedSet.has(m.name));\n\n return {\n tenantId,\n schemaName,\n appliedCount: applied.length,\n pendingCount: pending.length,\n pendingMigrations: pending.map((m) => m.name),\n status: pending.length > 0 ? 'behind' : 'ok',\n };\n } catch (error) {\n return {\n tenantId,\n schemaName,\n appliedCount: 0,\n pendingCount: 0,\n pendingMigrations: [],\n status: 'error',\n error: (error as Error).message,\n };\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Create a new tenant schema and optionally apply migrations\n */\n async createTenant(tenantId: string, options: CreateTenantOptions = {}): Promise<void> {\n const { migrate = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n // Create schema\n await pool.query(`CREATE SCHEMA IF NOT EXISTS \"${schemaName}\"`);\n\n if (migrate) {\n // Apply all migrations\n await this.migrateTenant(tenantId);\n }\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Drop a tenant schema\n */\n async dropTenant(tenantId: string, options: DropTenantOptions = {}): Promise<void> {\n const { cascade = true } = options;\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const cascadeSql = cascade ? 'CASCADE' : 'RESTRICT';\n await pool.query(`DROP SCHEMA IF EXISTS \"${schemaName}\" ${cascadeSql}`);\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Check if a tenant schema exists\n */\n async tenantExists(tenantId: string): Promise<boolean> {\n const schemaName = this.tenantConfig.isolation.schemaNameTemplate(tenantId);\n\n const pool = new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n });\n\n try {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.schemata WHERE schema_name = $1`,\n [schemaName]\n );\n return result.rowCount !== null && result.rowCount > 0;\n } finally {\n await pool.end();\n }\n }\n\n /**\n * Load migration files from the migrations folder\n */\n private async loadMigrations(): Promise<MigrationFile[]> {\n const files = await readdir(this.migratorConfig.migrationsFolder);\n\n const migrations: MigrationFile[] = [];\n\n for (const file of files) {\n if (!file.endsWith('.sql')) continue;\n\n const filePath = join(this.migratorConfig.migrationsFolder, file);\n const content = await readFile(filePath, 'utf-8');\n\n // Extract timestamp from filename (e.g., 0001_migration_name.sql)\n const match = file.match(/^(\\d+)_/);\n const timestamp = match?.[1] ? parseInt(match[1], 10) : 0;\n\n migrations.push({\n name: basename(file, '.sql'),\n path: filePath,\n sql: content,\n timestamp,\n });\n }\n\n // Sort by timestamp\n return migrations.sort((a, b) => a.timestamp - b.timestamp);\n }\n\n /**\n * Create a pool for a specific schema\n */\n private async createPool(schemaName: string): Promise<Pool> {\n return new Pool({\n connectionString: this.tenantConfig.connection.url,\n ...this.tenantConfig.connection.poolConfig,\n options: `-c search_path=\"${schemaName}\",public`,\n });\n }\n\n /**\n * Ensure migrations table exists\n */\n private async ensureMigrationsTable(pool: Pool, schemaName: string): Promise<void> {\n await pool.query(`\n CREATE TABLE IF NOT EXISTS \"${schemaName}\".\"${this.migrationsTable}\" (\n id SERIAL PRIMARY KEY,\n name VARCHAR(255) NOT NULL UNIQUE,\n applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n )\n `);\n }\n\n /**\n * Check if migrations table exists\n */\n private async migrationsTableExists(pool: Pool, schemaName: string): Promise<boolean> {\n const result = await pool.query(\n `SELECT 1 FROM information_schema.tables\n WHERE table_schema = $1 AND table_name = $2`,\n [schemaName, this.migrationsTable]\n );\n return result.rowCount !== null && result.rowCount > 0;\n }\n\n /**\n * Get applied migrations for a schema\n */\n private async getAppliedMigrations(pool: Pool, schemaName: string): Promise<AppliedMigration[]> {\n const result = await pool.query<{ id: number; name: string; applied_at: Date }>(\n `SELECT id, name, applied_at FROM \"${schemaName}\".\"${this.migrationsTable}\" ORDER BY id`\n );\n return result.rows.map((row) => ({\n id: row.id,\n name: row.name,\n appliedAt: row.applied_at,\n }));\n }\n\n /**\n * Apply a migration to a schema\n */\n private async applyMigration(pool: Pool, schemaName: string, migration: MigrationFile): Promise<void> {\n const client = await pool.connect();\n\n try {\n await client.query('BEGIN');\n\n // Execute migration SQL\n await client.query(migration.sql);\n\n // Record migration\n await client.query(\n `INSERT INTO \"${schemaName}\".\"${this.migrationsTable}\" (name) VALUES ($1)`,\n [migration.name]\n );\n\n await client.query('COMMIT');\n } catch (error) {\n await client.query('ROLLBACK');\n throw error;\n } finally {\n client.release();\n }\n }\n\n /**\n * Create a skipped result\n */\n private createSkippedResult(tenantId: string): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: 'Skipped due to abort',\n durationMs: 0,\n };\n }\n\n /**\n * Create an error result\n */\n private createErrorResult(tenantId: string, error: Error): TenantMigrationResult {\n return {\n tenantId,\n schemaName: this.tenantConfig.isolation.schemaNameTemplate(tenantId),\n success: false,\n appliedMigrations: [],\n error: error.message,\n durationMs: 0,\n };\n }\n\n /**\n * Aggregate migration results\n */\n private aggregateResults(results: TenantMigrationResult[]): MigrationResults {\n return {\n total: results.length,\n succeeded: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success && r.error !== 'Skipped due to abort').length,\n skipped: results.filter((r) => r.error === 'Skipped due to abort').length,\n details: results,\n };\n }\n}\n\n/**\n * Create a migrator instance\n */\nexport function createMigrator<\n TTenantSchema extends Record<string, unknown>,\n TSharedSchema extends Record<string, unknown>,\n>(\n tenantConfig: Config<TTenantSchema, TSharedSchema>,\n migratorConfig: MigratorConfig\n): Migrator<TTenantSchema, TSharedSchema> {\n return new Migrator(tenantConfig, migratorConfig);\n}\n","import ora, { type Ora } from 'ora';\nimport chalk from 'chalk';\n\n/**\n * Create a spinner instance\n */\nexport function createSpinner(text: string): Ora {\n return ora({\n text,\n color: 'cyan',\n });\n}\n\n/**\n * Format success message\n */\nexport function success(message: string): string {\n return chalk.green('✓ ') + message;\n}\n\n/**\n * Format error message\n */\nexport function error(message: string): string {\n return chalk.red('✗ ') + message;\n}\n\n/**\n * Format warning message\n */\nexport function warning(message: string): string {\n return chalk.yellow('⚠ ') + message;\n}\n\n/**\n * Format info message\n */\nexport function info(message: string): string {\n return chalk.blue('ℹ ') + message;\n}\n\n/**\n * Format dim text\n */\nexport function dim(message: string): string {\n return chalk.dim(message);\n}\n\n/**\n * Format bold text\n */\nexport function bold(message: string): string {\n return chalk.bold(message);\n}\n\n/**\n * Format cyan text\n */\nexport function cyan(message: string): string {\n return chalk.cyan(message);\n}\n\n/**\n * Format green text\n */\nexport function green(message: string): string {\n return chalk.green(message);\n}\n\n/**\n * Format red text\n */\nexport function red(message: string): string {\n return chalk.red(message);\n}\n\n/**\n * Format yellow text\n */\nexport function yellow(message: string): string {\n return chalk.yellow(message);\n}\n","import Table from 'cli-table3';\nimport chalk from 'chalk';\nimport type { TenantMigrationStatus } from '../../migrator/types.js';\n\n/**\n * Create a status table for tenant migrations\n */\nexport function createStatusTable(statuses: TenantMigrationStatus[]): string {\n const table = new Table({\n head: [\n chalk.cyan('Tenant'),\n chalk.cyan('Schema'),\n chalk.cyan('Applied'),\n chalk.cyan('Pending'),\n chalk.cyan('Status'),\n ],\n style: {\n head: [],\n border: [],\n },\n });\n\n for (const status of statuses) {\n const statusIcon = getStatusIcon(status.status);\n const statusText = getStatusText(status.status);\n\n table.push([\n status.tenantId,\n chalk.dim(status.schemaName),\n chalk.green(status.appliedCount.toString()),\n status.pendingCount > 0\n ? chalk.yellow(status.pendingCount.toString())\n : chalk.dim('0'),\n `${statusIcon} ${statusText}`,\n ]);\n }\n\n return table.toString();\n}\n\n/**\n * Create a results table for migration execution\n */\nexport function createResultsTable(\n results: Array<{\n tenantId: string;\n schemaName: string;\n success: boolean;\n appliedMigrations: string[];\n error?: string;\n durationMs: number;\n }>\n): string {\n const table = new Table({\n head: [\n chalk.cyan('Tenant'),\n chalk.cyan('Migrations'),\n chalk.cyan('Duration'),\n chalk.cyan('Status'),\n ],\n style: {\n head: [],\n border: [],\n },\n });\n\n for (const result of results) {\n const statusIcon = result.success ? chalk.green('✓') : chalk.red('✗');\n const statusText = result.success\n ? chalk.green('OK')\n : chalk.red(result.error ?? 'Failed');\n\n table.push([\n result.tenantId,\n result.appliedMigrations.length.toString(),\n `${result.durationMs}ms`,\n `${statusIcon} ${statusText}`,\n ]);\n }\n\n return table.toString();\n}\n\n/**\n * Create a pending migrations summary\n */\nexport function createPendingSummary(statuses: TenantMigrationStatus[]): string {\n const pendingMap = new Map<string, number>();\n\n for (const status of statuses) {\n for (const migration of status.pendingMigrations) {\n pendingMap.set(migration, (pendingMap.get(migration) || 0) + 1);\n }\n }\n\n if (pendingMap.size === 0) {\n return chalk.green('\\nAll tenants are up to date.');\n }\n\n const lines = [chalk.yellow('\\nPending migrations:')];\n\n for (const [migration, count] of pendingMap.entries()) {\n lines.push(\n ` ${chalk.dim('-')} ${migration} ${chalk.dim(`(${count} tenant${count > 1 ? 's' : ''})`)}`\n );\n }\n\n lines.push(\n chalk.dim('\\nRun \\'drizzle-multitenant migrate --all\\' to apply pending migrations.')\n );\n\n return lines.join('\\n');\n}\n\n/**\n * Get status icon\n */\nfunction getStatusIcon(status: 'ok' | 'behind' | 'error'): string {\n switch (status) {\n case 'ok':\n return chalk.green('✓');\n case 'behind':\n return chalk.yellow('⚠');\n case 'error':\n return chalk.red('✗');\n }\n}\n\n/**\n * Get status text\n */\nfunction getStatusText(status: 'ok' | 'behind' | 'error'): string {\n switch (status) {\n case 'ok':\n return chalk.green('OK');\n case 'behind':\n return chalk.yellow('Behind');\n case 'error':\n return chalk.red('Error');\n }\n}\n","import { pathToFileURL } from 'node:url';\nimport { resolve, extname } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { Config } from '../../types.js';\n\nconst CONFIG_FILE_NAMES = [\n 'tenant.config.ts',\n 'tenant.config.js',\n 'tenant.config.mjs',\n 'drizzle-multitenant.config.ts',\n 'drizzle-multitenant.config.js',\n 'drizzle-multitenant.config.mjs',\n];\n\nexport interface LoadedConfig {\n config: Config<Record<string, unknown>, Record<string, unknown>>;\n migrationsFolder?: string;\n migrationsTable?: string;\n tenantDiscovery?: () => Promise<string[]>;\n}\n\n/**\n * Load configuration from file\n */\nexport async function loadConfig(configPath?: string): Promise<LoadedConfig> {\n const cwd = process.cwd();\n\n let configFile: string | undefined;\n\n if (configPath) {\n configFile = resolve(cwd, configPath);\n if (!existsSync(configFile)) {\n throw new Error(`Config file not found: ${configFile}`);\n }\n } else {\n // Search for config file\n for (const name of CONFIG_FILE_NAMES) {\n const path = resolve(cwd, name);\n if (existsSync(path)) {\n configFile = path;\n break;\n }\n }\n }\n\n if (!configFile) {\n throw new Error(\n 'Config file not found. Create a tenant.config.ts or use --config flag.'\n );\n }\n\n // Handle TypeScript files\n const ext = extname(configFile);\n if (ext === '.ts') {\n // Register ts-node or tsx for TypeScript support\n await registerTypeScript();\n }\n\n // Import the config\n const configUrl = pathToFileURL(configFile).href;\n const module = await import(configUrl);\n const exported = module.default ?? module;\n\n if (!exported.connection || !exported.isolation || !exported.schemas) {\n throw new Error(\n 'Invalid config file. Expected an object with connection, isolation, and schemas properties.'\n );\n }\n\n return {\n config: exported,\n migrationsFolder: exported.migrations?.tenantFolder,\n migrationsTable: exported.migrations?.migrationsTable,\n tenantDiscovery: exported.migrations?.tenantDiscovery,\n };\n}\n\n/**\n * Register TypeScript loader\n */\nasync function registerTypeScript(): Promise<void> {\n try {\n // Try tsx first (faster)\n await import('tsx/esm');\n } catch {\n try {\n // Fall back to ts-node\n await import('ts-node/esm');\n } catch {\n throw new Error(\n 'TypeScript config requires tsx or ts-node. Install with: npm install -D tsx'\n );\n }\n }\n}\n\n/**\n * Resolve migrations folder path\n */\nexport function resolveMigrationsFolder(folder?: string): string {\n const cwd = process.cwd();\n const defaultFolder = './drizzle/tenant';\n\n const resolved = resolve(cwd, folder ?? defaultFolder);\n\n if (!existsSync(resolved)) {\n throw new Error(`Migrations folder not found: ${resolved}`);\n }\n\n return resolved;\n}\n","import { Command } from 'commander';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n createResultsTable,\n success,\n error,\n info,\n warning,\n bold,\n dim,\n} from '../utils/index.js';\n\nexport const migrateCommand = new Command('migrate')\n .description('Apply pending migrations to tenant schemas')\n .option('-c, --config <path>', 'Path to config file')\n .option('-a, --all', 'Migrate all tenants')\n .option('-t, --tenant <id>', 'Migrate a specific tenant')\n .option('--tenants <ids>', 'Migrate specific tenants (comma-separated)')\n .option('--concurrency <number>', 'Number of concurrent migrations', '10')\n .option('--dry-run', 'Show what would be applied without executing')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder, migrationsTable, tenantDiscovery } = await loadConfig(options.config);\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n // Determine tenant discovery function\n let discoveryFn: () => Promise<string[]>;\n\n if (options.tenant) {\n discoveryFn = async () => [options.tenant];\n } else if (options.tenants) {\n const tenantIds = options.tenants.split(',').map((id: string) => id.trim());\n discoveryFn = async () => tenantIds;\n } else if (options.all) {\n if (!tenantDiscovery) {\n throw new Error(\n 'No tenant discovery function configured. Add migrations.tenantDiscovery to your config.'\n );\n }\n discoveryFn = tenantDiscovery;\n } else {\n spinner.stop();\n console.log(error('Please specify --all, --tenant, or --tenants'));\n console.log(dim('\\nExamples:'));\n console.log(dim(' npx drizzle-multitenant migrate --all'));\n console.log(dim(' npx drizzle-multitenant migrate --tenant=tenant-uuid'));\n console.log(dim(' npx drizzle-multitenant migrate --tenants=tenant-1,tenant-2'));\n process.exit(1);\n }\n\n spinner.text = 'Discovering tenants...';\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n migrationsTable,\n tenantDiscovery: discoveryFn,\n });\n\n const tenantIds = await discoveryFn();\n\n if (tenantIds.length === 0) {\n spinner.stop();\n console.log(warning('No tenants found.'));\n return;\n }\n\n spinner.text = `Found ${tenantIds.length} tenant${tenantIds.length > 1 ? 's' : ''}`;\n spinner.succeed();\n\n if (options.dryRun) {\n console.log(info(bold('\\nDry run mode - no changes will be made\\n')));\n }\n\n console.log(info(`Migrating ${tenantIds.length} tenant${tenantIds.length > 1 ? 's' : ''}...\\n`));\n\n const concurrency = parseInt(options.concurrency, 10);\n let completed = 0;\n\n const results = await migrator.migrateAll({\n concurrency,\n dryRun: options.dryRun,\n onProgress: (tenantId, status, migrationName) => {\n if (status === 'completed') {\n completed++;\n const progress = `[${completed}/${tenantIds.length}]`;\n console.log(`${dim(progress)} ${success(tenantId)}`);\n } else if (status === 'failed') {\n completed++;\n const progress = `[${completed}/${tenantIds.length}]`;\n console.log(`${dim(progress)} ${error(tenantId)}`);\n } else if (status === 'migrating' && migrationName) {\n // Optional: show individual migration progress\n }\n },\n onError: (tenantId, err) => {\n console.log(error(`${tenantId}: ${err.message}`));\n return 'continue';\n },\n });\n\n console.log('\\n' + bold('Results:'));\n console.log(createResultsTable(results.details));\n\n console.log('\\n' + bold('Summary:'));\n console.log(` Total: ${results.total}`);\n console.log(` Succeeded: ${success(results.succeeded.toString())}`);\n if (results.failed > 0) {\n console.log(` Failed: ${error(results.failed.toString())}`);\n }\n if (results.skipped > 0) {\n console.log(` Skipped: ${warning(results.skipped.toString())}`);\n }\n\n if (results.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n createStatusTable,\n createPendingSummary,\n error,\n bold,\n} from '../utils/index.js';\n\nexport const statusCommand = new Command('status')\n .description('Show migration status for all tenants')\n .option('-c, --config <path>', 'Path to config file')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder, migrationsTable, tenantDiscovery } = await loadConfig(options.config);\n\n if (!tenantDiscovery) {\n throw new Error(\n 'No tenant discovery function configured. Add migrations.tenantDiscovery to your config.'\n );\n }\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n spinner.text = 'Discovering tenants...';\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n migrationsTable,\n tenantDiscovery,\n });\n\n spinner.text = 'Fetching migration status...';\n\n const statuses = await migrator.getStatus();\n\n spinner.succeed(`Found ${statuses.length} tenant${statuses.length > 1 ? 's' : ''}`);\n\n console.log('\\n' + bold('Migration Status:'));\n console.log(createStatusTable(statuses));\n console.log(createPendingSummary(statuses));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { writeFile, mkdir, readdir } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport {\n loadConfig,\n createSpinner,\n success,\n error,\n dim,\n} from '../utils/index.js';\n\nexport const generateCommand = new Command('generate')\n .description('Generate a new migration file')\n .requiredOption('-n, --name <name>', 'Migration name')\n .option('-c, --config <path>', 'Path to config file')\n .option('--type <type>', 'Migration type: tenant or shared', 'tenant')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { migrationsFolder: configFolder } = await loadConfig(options.config);\n\n const cwd = process.cwd();\n let folder: string;\n\n if (options.migrationsFolder) {\n folder = resolve(cwd, options.migrationsFolder);\n } else if (configFolder) {\n folder = resolve(cwd, configFolder);\n } else {\n folder = resolve(cwd, options.type === 'shared' ? './drizzle/shared' : './drizzle/tenant');\n }\n\n // Ensure folder exists\n if (!existsSync(folder)) {\n await mkdir(folder, { recursive: true });\n spinner.text = `Created migrations folder: ${folder}`;\n }\n\n spinner.text = 'Generating migration...';\n\n // Get next sequence number\n const files = existsSync(folder) ? await readdir(folder) : [];\n const sqlFiles = files.filter((f) => f.endsWith('.sql'));\n\n let maxSequence = 0;\n for (const file of sqlFiles) {\n const match = file.match(/^(\\d+)_/);\n if (match) {\n const seq = parseInt(match[1], 10);\n if (seq > maxSequence) {\n maxSequence = seq;\n }\n }\n }\n\n const nextSequence = (maxSequence + 1).toString().padStart(4, '0');\n const safeName = options.name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '_')\n .replace(/^_|_$/g, '');\n\n const fileName = `${nextSequence}_${safeName}.sql`;\n const filePath = join(folder, fileName);\n\n // Create migration file with template\n const template = `-- Migration: ${options.name}\n-- Created at: ${new Date().toISOString()}\n-- Type: ${options.type}\n\n-- Write your SQL migration here\n\n`;\n\n await writeFile(filePath, template, 'utf-8');\n\n spinner.succeed('Migration generated');\n\n console.log('\\n' + success(`Created: ${dim(filePath)}`));\n console.log(dim('\\nEdit this file to add your migration SQL.'));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n success,\n error,\n warning,\n dim,\n} from '../utils/index.js';\n\nexport const tenantCreateCommand = new Command('tenant:create')\n .description('Create a new tenant schema and apply all migrations')\n .requiredOption('--id <tenantId>', 'Tenant ID')\n .option('-c, --config <path>', 'Path to config file')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .option('--no-migrate', 'Skip applying migrations after creating schema')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder, migrationsTable } = await loadConfig(options.config);\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n migrationsTable,\n tenantDiscovery: async () => [],\n });\n\n const schemaName = config.isolation.schemaNameTemplate(options.id);\n\n spinner.text = `Checking if tenant ${options.id} exists...`;\n\n const exists = await migrator.tenantExists(options.id);\n if (exists) {\n spinner.warn(`Tenant ${options.id} already exists (${schemaName})`);\n\n if (options.migrate) {\n spinner.start();\n spinner.text = 'Applying pending migrations...';\n\n const result = await migrator.migrateTenant(options.id);\n\n if (result.appliedMigrations.length > 0) {\n spinner.succeed(`Applied ${result.appliedMigrations.length} migration(s)`);\n for (const migration of result.appliedMigrations) {\n console.log(` ${dim('-')} ${migration}`);\n }\n } else {\n spinner.succeed('No pending migrations');\n }\n }\n\n return;\n }\n\n spinner.text = `Creating tenant schema ${schemaName}...`;\n\n await migrator.createTenant(options.id, {\n migrate: options.migrate,\n });\n\n spinner.succeed(`Tenant ${options.id} created`);\n\n console.log('\\n' + success('Schema created: ') + dim(schemaName));\n\n if (options.migrate) {\n console.log(success('All migrations applied'));\n } else {\n console.log(warning('Migrations skipped. Run migrate to apply.'));\n }\n\n console.log(dim('\\nYou can now use this tenant:'));\n console.log(dim(` const db = tenants.getDb('${options.id}');`));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createInterface } from 'node:readline';\nimport { createMigrator } from '../../migrator/migrator.js';\nimport {\n loadConfig,\n resolveMigrationsFolder,\n createSpinner,\n success,\n error,\n warning,\n dim,\n red,\n bold,\n} from '../utils/index.js';\n\nexport const tenantDropCommand = new Command('tenant:drop')\n .description('Drop a tenant schema (DESTRUCTIVE)')\n .requiredOption('--id <tenantId>', 'Tenant ID')\n .option('-c, --config <path>', 'Path to config file')\n .option('--migrations-folder <path>', 'Path to migrations folder')\n .option('-f, --force', 'Skip confirmation prompt')\n .option('--no-cascade', 'Use RESTRICT instead of CASCADE')\n .action(async (options) => {\n const spinner = createSpinner('Loading configuration...');\n\n try {\n spinner.start();\n\n const { config, migrationsFolder, migrationsTable } = await loadConfig(options.config);\n\n const folder = options.migrationsFolder\n ? resolveMigrationsFolder(options.migrationsFolder)\n : resolveMigrationsFolder(migrationsFolder);\n\n const migrator = createMigrator(config, {\n migrationsFolder: folder,\n migrationsTable,\n tenantDiscovery: async () => [],\n });\n\n const schemaName = config.isolation.schemaNameTemplate(options.id);\n\n spinner.text = `Checking if tenant ${options.id} exists...`;\n\n const exists = await migrator.tenantExists(options.id);\n if (!exists) {\n spinner.warn(`Tenant ${options.id} does not exist`);\n return;\n }\n\n spinner.stop();\n\n // Confirmation prompt\n if (!options.force) {\n console.log(red(bold('\\n⚠️ WARNING: This action is DESTRUCTIVE and IRREVERSIBLE!')));\n console.log(dim(`\\nYou are about to drop schema: ${schemaName}`));\n console.log(dim('All tables and data in this schema will be permanently deleted.\\n'));\n\n const confirmed = await askConfirmation(\n `Type \"${options.id}\" to confirm deletion: `,\n options.id\n );\n\n if (!confirmed) {\n console.log('\\n' + warning('Operation cancelled.'));\n return;\n }\n }\n\n spinner.start();\n spinner.text = `Dropping tenant schema ${schemaName}...`;\n\n await migrator.dropTenant(options.id, {\n cascade: options.cascade,\n });\n\n spinner.succeed(`Tenant ${options.id} dropped`);\n\n console.log('\\n' + success('Schema deleted: ') + dim(schemaName));\n } catch (err) {\n spinner.fail((err as Error).message);\n process.exit(1);\n }\n });\n\n/**\n * Ask for confirmation\n */\nasync function askConfirmation(question: string, expected: string): Promise<boolean> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim() === expected);\n });\n });\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander';\nimport {\n migrateCommand,\n statusCommand,\n generateCommand,\n tenantCreateCommand,\n tenantDropCommand,\n} from './commands/index.js';\n\nconst program = new Command();\n\nprogram\n .name('drizzle-multitenant')\n .description('Multi-tenancy toolkit for Drizzle ORM')\n .version('0.3.0');\n\n// Register commands\nprogram.addCommand(migrateCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(generateCommand);\nprogram.addCommand(tenantCreateCommand);\nprogram.addCommand(tenantDropCommand);\n\n// Parse arguments\nprogram.parse();\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drizzle-multitenant",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Multi-tenancy toolkit for Drizzle ORM with schema isolation, tenant context, and parallel migrations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/roadmap.md CHANGED
@@ -42,6 +42,14 @@
42
42
  - [x] 148 testes passando
43
43
  - [x] Licença MIT
44
44
 
45
+ ### v1.0.3 - NestJS DX Improvements
46
+ - [x] `TenantDbFactory` para singleton services (cron jobs, event handlers)
47
+ - [x] `@InjectTenantDbFactory()` decorator
48
+ - [x] Debug utilities para proxies (`__debug`, `__tenantId`, `__isProxy`)
49
+ - [x] `console.log(tenantDb)` mostra informações úteis
50
+ - [x] CLI `migrationsTable` config support
51
+ - [x] 154 testes passando
52
+
45
53
  ---
46
54
 
47
55
  ## Próximas Versões
@@ -792,13 +800,103 @@ const stats = await adminQuery
792
800
 
793
801
  ## Quick Wins (Podem entrar em qualquer versão)
794
802
 
795
- | Feature | Esforço | Versão |
796
- |---------|---------|--------|
797
- | Health check API | 2h | v1.1.0 |
798
- | Schema name sanitization | 1h | v1.2.0 |
799
- | CLI interativo básico | 4h | v1.5.0 |
800
- | Structured logging hook | 2h | v1.1.0 |
801
- | Tenant clone (schema only) | 4h | v1.5.0 |
803
+ | Feature | Esforço | Versão | Status |
804
+ |---------|---------|--------|--------|
805
+ | Health check API | 2h | v1.1.0 | Pendente |
806
+ | Schema name sanitization | 1h | v1.2.0 | Pendente |
807
+ | CLI interativo básico | 4h | v1.5.0 | Pendente |
808
+ | Structured logging hook | 2h | v1.1.0 | Pendente |
809
+ | Tenant clone (schema only) | 4h | v1.5.0 | Pendente |
810
+ | ~~CLI migrationsTable config~~ | 1h | v1.0.3 | **Concluído** |
811
+ | ~~TenantDbFactory para singletons~~ | 2h | v1.0.3 | **Concluído** |
812
+ | ~~Debug utilities para proxies~~ | 1h | v1.0.3 | **Concluído** |
813
+
814
+ ---
815
+
816
+ ## v1.0.4 - CLI migrationsTable Support
817
+
818
+ ### Problema
819
+
820
+ A CLI do `drizzle-multitenant` usa a tabela `__drizzle_migrations` para tracking de migrations, mas não permite configurar um nome diferente. Isso causa incompatibilidade com projetos que já usam outra tabela de tracking (ex: `__drizzle_tenant_migrations`).
821
+
822
+ ### Solução
823
+
824
+ Ler o campo `migrationsTable` do objeto `migrations` na config e passá-lo para o `Migrator`.
825
+
826
+ ### Mudanças Necessárias
827
+
828
+ #### 1. Atualizar `loadConfig` em `src/cli/utils.ts`
829
+
830
+ ```typescript
831
+ export async function loadConfig(configPath?: string) {
832
+ // ... código existente ...
833
+
834
+ return {
835
+ config: exported,
836
+ migrationsFolder: exported.migrations?.tenantFolder,
837
+ tenantDiscovery: exported.migrations?.tenantDiscovery,
838
+ migrationsTable: exported.migrations?.migrationsTable, // NOVO
839
+ };
840
+ }
841
+ ```
842
+
843
+ #### 2. Atualizar comandos em `src/cli/commands/`
844
+
845
+ Passar `migrationsTable` para o `createMigrator`:
846
+
847
+ ```typescript
848
+ // migrate.ts, status.ts, tenant-create.ts, tenant-drop.ts
849
+ const { config, migrationsFolder, tenantDiscovery, migrationsTable } = await loadConfig(options.config);
850
+
851
+ const migrator = createMigrator(config, {
852
+ migrationsFolder: folder,
853
+ tenantDiscovery: discoveryFn,
854
+ migrationsTable, // NOVO - passa undefined se não configurado (usa default)
855
+ });
856
+ ```
857
+
858
+ #### 3. Atualizar tipos
859
+
860
+ ```typescript
861
+ // types.ts ou onde apropriado
862
+ interface MigrationsConfig {
863
+ tenantFolder: string;
864
+ tenantDiscovery: () => Promise<string[]>;
865
+ migrationsTable?: string; // NOVO
866
+ }
867
+ ```
868
+
869
+ ### Exemplo de Uso
870
+
871
+ ```typescript
872
+ // tenant.config.ts
873
+ export default {
874
+ ...config,
875
+ migrations: {
876
+ tenantFolder: "./drizzle/tenant",
877
+ tenantDiscovery: discoverTenants,
878
+ migrationsTable: "__drizzle_tenant_migrations", // NOVO - usa tabela customizada
879
+ },
880
+ };
881
+ ```
882
+
883
+ ### Compatibilidade
884
+
885
+ - **Backward compatible**: Se não configurado, usa `__drizzle_migrations` (comportamento atual)
886
+ - **Migration path**: Projetos existentes podem:
887
+ 1. Configurar a tabela antiga na config
888
+ 2. Ou renomear a tabela no banco para o novo padrão
889
+
890
+ ### Checklist
891
+
892
+ - [x] Atualizar `loadConfig` para extrair `migrationsTable`
893
+ - [x] Atualizar `migrate` command
894
+ - [x] Atualizar `status` command
895
+ - [x] Atualizar `tenant:create` command
896
+ - [x] Atualizar `tenant:drop` command
897
+ - [x] Adicionar teste unitário
898
+ - [x] Atualizar README com exemplo
899
+ - [x] ~~Publicar v1.0.4~~ (incluído em v1.0.3)
802
900
 
803
901
  ---
804
902