drizzle-multitenant 1.0.2 → 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 +75 -2
- package/dist/cli/index.js +9 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/integrations/nestjs/index.d.ts +159 -3
- package/dist/integrations/nestjs/index.js +177 -29
- package/dist/integrations/nestjs/index.js.map +1 -1
- package/package.json +1 -1
- package/roadmap.md +105 -7
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
|
|
|
@@ -134,7 +143,7 @@ import { TenantModule, InjectTenantDb } from 'drizzle-multitenant/nestjs';
|
|
|
134
143
|
})
|
|
135
144
|
export class AppModule {}
|
|
136
145
|
|
|
137
|
-
@Injectable()
|
|
146
|
+
@Injectable({ scope: Scope.REQUEST })
|
|
138
147
|
export class UserService {
|
|
139
148
|
constructor(@InjectTenantDb() private readonly db: TenantDb) {}
|
|
140
149
|
|
|
@@ -144,6 +153,59 @@ export class UserService {
|
|
|
144
153
|
}
|
|
145
154
|
```
|
|
146
155
|
|
|
156
|
+
#### Singleton Services (Cron Jobs, Event Handlers)
|
|
157
|
+
|
|
158
|
+
Use `TenantDbFactory` when you need to access tenant databases from singleton services:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import { TenantDbFactory, InjectTenantDbFactory } from 'drizzle-multitenant/nestjs';
|
|
162
|
+
|
|
163
|
+
@Injectable() // Singleton - no scope needed
|
|
164
|
+
export class ReportService {
|
|
165
|
+
constructor(@InjectTenantDbFactory() private dbFactory: TenantDbFactory) {}
|
|
166
|
+
|
|
167
|
+
async generateReport(tenantId: string) {
|
|
168
|
+
const db = this.dbFactory.getDb(tenantId);
|
|
169
|
+
return db.select().from(reports);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Cron job example
|
|
174
|
+
@Injectable()
|
|
175
|
+
export class DailyReportCron {
|
|
176
|
+
constructor(@InjectTenantDbFactory() private dbFactory: TenantDbFactory) {}
|
|
177
|
+
|
|
178
|
+
@Cron('0 8 * * *')
|
|
179
|
+
async run() {
|
|
180
|
+
const tenants = await this.getTenantIds();
|
|
181
|
+
for (const tenantId of tenants) {
|
|
182
|
+
const db = this.dbFactory.getDb(tenantId);
|
|
183
|
+
await this.processReports(db);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
#### Debugging
|
|
190
|
+
|
|
191
|
+
The injected `TenantDb` provides debug utilities:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// Console output shows useful info
|
|
195
|
+
console.log(tenantDb);
|
|
196
|
+
// [TenantDb] tenant=123 schema=empresa_123
|
|
197
|
+
|
|
198
|
+
// Access debug information
|
|
199
|
+
console.log(tenantDb.__debug);
|
|
200
|
+
// { tenantId: '123', schemaName: 'empresa_123', isProxy: true, poolCount: 5 }
|
|
201
|
+
|
|
202
|
+
// Quick access
|
|
203
|
+
console.log(tenantDb.__tenantId); // '123'
|
|
204
|
+
|
|
205
|
+
// In tests
|
|
206
|
+
expect(tenantDb.__tenantId).toBe('expected-tenant');
|
|
207
|
+
```
|
|
208
|
+
|
|
147
209
|
## CLI Commands
|
|
148
210
|
|
|
149
211
|
```bash
|
|
@@ -222,13 +284,24 @@ const result = await query
|
|
|
222
284
|
|
|
223
285
|
| Decorator | Description |
|
|
224
286
|
|-----------|-------------|
|
|
225
|
-
| `@InjectTenantDb()` | Inject tenant database |
|
|
287
|
+
| `@InjectTenantDb()` | Inject tenant database (request-scoped) |
|
|
288
|
+
| `@InjectTenantDbFactory()` | Inject factory for singleton services |
|
|
226
289
|
| `@InjectSharedDb()` | Inject shared database |
|
|
227
290
|
| `@InjectTenantContext()` | Inject tenant context |
|
|
228
291
|
| `@InjectTenantManager()` | Inject tenant manager |
|
|
229
292
|
| `@RequiresTenant()` | Mark route as requiring tenant |
|
|
230
293
|
| `@PublicRoute()` | Mark route as public |
|
|
231
294
|
|
|
295
|
+
### TenantDbFactory Methods
|
|
296
|
+
|
|
297
|
+
| Method | Description |
|
|
298
|
+
|--------|-------------|
|
|
299
|
+
| `getDb(tenantId)` | Get Drizzle instance for tenant |
|
|
300
|
+
| `getSharedDb()` | Get shared database instance |
|
|
301
|
+
| `getSchemaName(tenantId)` | Get schema name for tenant |
|
|
302
|
+
| `getDebugInfo(tenantId)` | Get debug info (tenantId, schema, pool stats) |
|
|
303
|
+
| `getManager()` | Get underlying TenantManager |
|
|
304
|
+
|
|
232
305
|
## Requirements
|
|
233
306
|
|
|
234
307
|
- Node.js 18+
|
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);
|
package/dist/cli/index.js.map
CHANGED
|
@@ -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"]}
|