drizzle-multitenant 1.0.0
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/.claude/settings.local.json +14 -0
- package/LICENSE +21 -0
- package/README.md +262 -0
- package/bin/drizzle-multitenant.js +2 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +866 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context-DBerWr50.d.ts +76 -0
- package/dist/cross-schema/index.d.ts +262 -0
- package/dist/cross-schema/index.js +219 -0
- package/dist/cross-schema/index.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.js +935 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/express.d.ts +93 -0
- package/dist/integrations/express.js +110 -0
- package/dist/integrations/express.js.map +1 -0
- package/dist/integrations/fastify.d.ts +92 -0
- package/dist/integrations/fastify.js +236 -0
- package/dist/integrations/fastify.js.map +1 -0
- package/dist/integrations/hono.d.ts +2 -0
- package/dist/integrations/hono.js +3 -0
- package/dist/integrations/hono.js.map +1 -0
- package/dist/integrations/nestjs/index.d.ts +386 -0
- package/dist/integrations/nestjs/index.js +9828 -0
- package/dist/integrations/nestjs/index.js.map +1 -0
- package/dist/migrator/index.d.ts +208 -0
- package/dist/migrator/index.js +390 -0
- package/dist/migrator/index.js.map +1 -0
- package/dist/types-DKVaTaIb.d.ts +130 -0
- package/package.json +102 -0
|
@@ -0,0 +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"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { T as TenantManager, a as TenantDb, S as SharedDb } from './types-DKVaTaIb.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base tenant context data
|
|
5
|
+
*/
|
|
6
|
+
interface BaseTenantContext {
|
|
7
|
+
tenantId: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Tenant context with optional custom data
|
|
11
|
+
*/
|
|
12
|
+
type TenantContextData<TCustom extends Record<string, unknown> = Record<string, unknown>> = BaseTenantContext & TCustom;
|
|
13
|
+
/**
|
|
14
|
+
* Tenant context API
|
|
15
|
+
*/
|
|
16
|
+
interface TenantContext<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown>, TCustom extends Record<string, unknown> = Record<string, unknown>> {
|
|
17
|
+
/**
|
|
18
|
+
* Run a callback with tenant context
|
|
19
|
+
*/
|
|
20
|
+
runWithTenant<T>(context: TenantContextData<TCustom>, callback: () => T | Promise<T>): T | Promise<T>;
|
|
21
|
+
/**
|
|
22
|
+
* Get current tenant context (throws if not in context)
|
|
23
|
+
*/
|
|
24
|
+
getTenant(): TenantContextData<TCustom>;
|
|
25
|
+
/**
|
|
26
|
+
* Get current tenant context or undefined
|
|
27
|
+
*/
|
|
28
|
+
getTenantOrNull(): TenantContextData<TCustom> | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Get current tenant ID (throws if not in context)
|
|
31
|
+
*/
|
|
32
|
+
getTenantId(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Get database for current tenant (throws if not in context)
|
|
35
|
+
*/
|
|
36
|
+
getTenantDb(): TenantDb<TTenantSchema>;
|
|
37
|
+
/**
|
|
38
|
+
* Get shared database
|
|
39
|
+
*/
|
|
40
|
+
getSharedDb(): SharedDb<TSharedSchema>;
|
|
41
|
+
/**
|
|
42
|
+
* Check if currently running within a tenant context
|
|
43
|
+
*/
|
|
44
|
+
isInTenantContext(): boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create a tenant context with AsyncLocalStorage
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* import { createTenantContext, createTenantManager } from 'drizzle-multitenant';
|
|
52
|
+
*
|
|
53
|
+
* const manager = createTenantManager(config);
|
|
54
|
+
*
|
|
55
|
+
* const {
|
|
56
|
+
* runWithTenant,
|
|
57
|
+
* getTenant,
|
|
58
|
+
* getTenantDb,
|
|
59
|
+
* getSharedDb,
|
|
60
|
+
* } = createTenantContext(manager);
|
|
61
|
+
*
|
|
62
|
+
* // Use in request handler
|
|
63
|
+
* app.get('/users', async (req, res) => {
|
|
64
|
+
* const tenantId = req.headers['x-tenant-id'];
|
|
65
|
+
*
|
|
66
|
+
* await runWithTenant({ tenantId }, async () => {
|
|
67
|
+
* const db = getTenantDb();
|
|
68
|
+
* const users = await db.select().from(schema.users);
|
|
69
|
+
* res.json(users);
|
|
70
|
+
* });
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function createTenantContext<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>, TCustom extends Record<string, unknown> = Record<string, unknown>>(manager: TenantManager<TTenantSchema, TSharedSchema>): TenantContext<TTenantSchema, TSharedSchema, TCustom>;
|
|
75
|
+
|
|
76
|
+
export { type BaseTenantContext as B, type TenantContextData as T, type TenantContext as a, createTenantContext as c };
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
2
|
+
import { SQL, Table, Column } from 'drizzle-orm';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Schema source identifier
|
|
6
|
+
*/
|
|
7
|
+
type SchemaSource = 'tenant' | 'shared';
|
|
8
|
+
/**
|
|
9
|
+
* Cross-schema query context
|
|
10
|
+
*/
|
|
11
|
+
interface CrossSchemaContext<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
12
|
+
tenantDb: NodePgDatabase<TTenantSchema>;
|
|
13
|
+
sharedDb: NodePgDatabase<TSharedSchema>;
|
|
14
|
+
tenantSchema?: string;
|
|
15
|
+
sharedSchema?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Join condition type
|
|
19
|
+
*/
|
|
20
|
+
type JoinCondition = SQL<unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Join type
|
|
23
|
+
*/
|
|
24
|
+
type JoinType = 'inner' | 'left' | 'right' | 'full';
|
|
25
|
+
/**
|
|
26
|
+
* Table reference with schema
|
|
27
|
+
*/
|
|
28
|
+
interface TableReference<T extends Table = Table> {
|
|
29
|
+
table: T;
|
|
30
|
+
source: SchemaSource;
|
|
31
|
+
alias?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Join definition
|
|
35
|
+
*/
|
|
36
|
+
interface JoinDefinition<T extends Table = Table> {
|
|
37
|
+
table: T;
|
|
38
|
+
source: SchemaSource;
|
|
39
|
+
condition: JoinCondition;
|
|
40
|
+
type: JoinType;
|
|
41
|
+
alias?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Select field definition
|
|
45
|
+
*/
|
|
46
|
+
interface SelectField<TColumn extends Column = Column> {
|
|
47
|
+
column: TColumn;
|
|
48
|
+
alias?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Cross-schema query builder state
|
|
52
|
+
*/
|
|
53
|
+
interface QueryBuilderState<TFrom extends Table = Table, TSelect extends Record<string, Column> = Record<string, Column>> {
|
|
54
|
+
from: TableReference<TFrom>;
|
|
55
|
+
joins: JoinDefinition[];
|
|
56
|
+
select: TSelect;
|
|
57
|
+
where?: SQL<unknown>;
|
|
58
|
+
orderBy?: SQL<unknown>[];
|
|
59
|
+
limit?: number;
|
|
60
|
+
offset?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Lookup configuration for withSharedLookup
|
|
64
|
+
*/
|
|
65
|
+
interface SharedLookupConfig<TTenantTable extends Table, TSharedTable extends Table, TSharedFields extends keyof TSharedTable['_']['columns']> {
|
|
66
|
+
tenantDb: NodePgDatabase<Record<string, unknown>>;
|
|
67
|
+
sharedDb: NodePgDatabase<Record<string, unknown>>;
|
|
68
|
+
tenantTable: TTenantTable;
|
|
69
|
+
sharedTable: TSharedTable;
|
|
70
|
+
foreignKey: keyof TTenantTable['_']['columns'];
|
|
71
|
+
sharedKey?: keyof TSharedTable['_']['columns'];
|
|
72
|
+
sharedFields: TSharedFields[];
|
|
73
|
+
where?: SQL<unknown>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Infer result type from lookup config
|
|
77
|
+
*/
|
|
78
|
+
type LookupResult<TTenantTable extends Table, TSharedTable extends Table, TSharedFields extends keyof TSharedTable['_']['columns']> = {
|
|
79
|
+
[K in keyof TTenantTable['_']['columns']]: TTenantTable['_']['columns'][K]['_']['data'];
|
|
80
|
+
} & {
|
|
81
|
+
[K in TSharedFields]?: TSharedTable['_']['columns'][K]['_']['data'];
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Raw cross-schema query options
|
|
85
|
+
*/
|
|
86
|
+
interface CrossSchemaRawOptions {
|
|
87
|
+
tenantSchema: string;
|
|
88
|
+
sharedSchema: string;
|
|
89
|
+
sql: string;
|
|
90
|
+
params?: unknown[];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Column selection helper type
|
|
94
|
+
*/
|
|
95
|
+
type ColumnSelection<T extends Table> = {
|
|
96
|
+
[K in keyof T['_']['columns']]?: boolean;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Infer selected columns type
|
|
100
|
+
*/
|
|
101
|
+
type InferSelectedColumns<T extends Table, TSelection extends ColumnSelection<T>> = {
|
|
102
|
+
[K in keyof TSelection as TSelection[K] extends true ? K : never]: T['_']['columns'][K extends keyof T['_']['columns'] ? K : never]['_']['data'];
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Cross-schema query builder for joining tenant and shared data
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const query = createCrossSchemaQuery({
|
|
111
|
+
* tenantDb: tenants.getDb('tenant-uuid'),
|
|
112
|
+
* sharedDb: tenants.getSharedDb(),
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* const results = await query
|
|
116
|
+
* .from('tenant', orders)
|
|
117
|
+
* .leftJoin('shared', subscriptionPlans, eq(orders.planId, subscriptionPlans.id))
|
|
118
|
+
* .select({
|
|
119
|
+
* orderId: orders.id,
|
|
120
|
+
* planName: subscriptionPlans.name,
|
|
121
|
+
* })
|
|
122
|
+
* .execute();
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
declare class CrossSchemaQueryBuilder<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
126
|
+
private readonly context;
|
|
127
|
+
private fromTable;
|
|
128
|
+
private joins;
|
|
129
|
+
private selectFields;
|
|
130
|
+
private whereCondition;
|
|
131
|
+
private orderByFields;
|
|
132
|
+
private limitValue;
|
|
133
|
+
private offsetValue;
|
|
134
|
+
constructor(context: CrossSchemaContext<TTenantSchema, TSharedSchema>);
|
|
135
|
+
/**
|
|
136
|
+
* Set the main table to query from
|
|
137
|
+
*/
|
|
138
|
+
from<T extends Table>(source: SchemaSource, table: T): this;
|
|
139
|
+
/**
|
|
140
|
+
* Add an inner join
|
|
141
|
+
*/
|
|
142
|
+
innerJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this;
|
|
143
|
+
/**
|
|
144
|
+
* Add a left join
|
|
145
|
+
*/
|
|
146
|
+
leftJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this;
|
|
147
|
+
/**
|
|
148
|
+
* Add a right join
|
|
149
|
+
*/
|
|
150
|
+
rightJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this;
|
|
151
|
+
/**
|
|
152
|
+
* Add a full outer join
|
|
153
|
+
*/
|
|
154
|
+
fullJoin<T extends Table>(source: SchemaSource, table: T, condition: JoinCondition): this;
|
|
155
|
+
/**
|
|
156
|
+
* Select specific fields
|
|
157
|
+
*/
|
|
158
|
+
select<T extends Record<string, Column>>(fields: T): this;
|
|
159
|
+
/**
|
|
160
|
+
* Add a where condition
|
|
161
|
+
*/
|
|
162
|
+
where(condition: SQL<unknown>): this;
|
|
163
|
+
/**
|
|
164
|
+
* Add order by
|
|
165
|
+
*/
|
|
166
|
+
orderBy(...fields: SQL<unknown>[]): this;
|
|
167
|
+
/**
|
|
168
|
+
* Set limit
|
|
169
|
+
*/
|
|
170
|
+
limit(value: number): this;
|
|
171
|
+
/**
|
|
172
|
+
* Set offset
|
|
173
|
+
*/
|
|
174
|
+
offset(value: number): this;
|
|
175
|
+
/**
|
|
176
|
+
* Execute the query and return typed results
|
|
177
|
+
*/
|
|
178
|
+
execute<TResult = Record<string, unknown>>(): Promise<TResult[]>;
|
|
179
|
+
/**
|
|
180
|
+
* Build the SQL query
|
|
181
|
+
*/
|
|
182
|
+
private buildSql;
|
|
183
|
+
/**
|
|
184
|
+
* Add a join to the query
|
|
185
|
+
*/
|
|
186
|
+
private addJoin;
|
|
187
|
+
/**
|
|
188
|
+
* Get schema name for a source
|
|
189
|
+
*/
|
|
190
|
+
private getSchemaName;
|
|
191
|
+
/**
|
|
192
|
+
* Get fully qualified table name
|
|
193
|
+
*/
|
|
194
|
+
private getFullTableName;
|
|
195
|
+
/**
|
|
196
|
+
* Get SQL keyword for join type
|
|
197
|
+
*/
|
|
198
|
+
private getJoinKeyword;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Create a cross-schema query builder
|
|
202
|
+
*/
|
|
203
|
+
declare function createCrossSchemaQuery<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>>(context: CrossSchemaContext<TTenantSchema, TSharedSchema>): CrossSchemaQueryBuilder<TTenantSchema, TSharedSchema>;
|
|
204
|
+
/**
|
|
205
|
+
* Helper for common pattern: tenant table with shared lookup
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* const ordersWithPlans = await withSharedLookup({
|
|
210
|
+
* tenantDb,
|
|
211
|
+
* sharedDb,
|
|
212
|
+
* tenantTable: orders,
|
|
213
|
+
* sharedTable: subscriptionPlans,
|
|
214
|
+
* foreignKey: 'planId',
|
|
215
|
+
* sharedFields: ['name', 'features', 'price'],
|
|
216
|
+
* });
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
declare function withSharedLookup<TTenantTable extends Table, TSharedTable extends Table, TSharedFields extends keyof TSharedTable['_']['columns']>(config: SharedLookupConfig<TTenantTable, TSharedTable, TSharedFields>): Promise<Array<Record<string, unknown>>>;
|
|
220
|
+
/**
|
|
221
|
+
* Execute raw cross-schema SQL with type safety
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* const result = await crossSchemaRaw<{ userName: string; planName: string }>({
|
|
226
|
+
* tenantSchema: 'tenant_abc123',
|
|
227
|
+
* sharedSchema: 'public',
|
|
228
|
+
* sql: `
|
|
229
|
+
* SELECT u.name as "userName", p.name as "planName"
|
|
230
|
+
* FROM $tenant.users u
|
|
231
|
+
* JOIN $shared.plans p ON u.plan_id = p.id
|
|
232
|
+
* `,
|
|
233
|
+
* });
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
declare function crossSchemaRaw<TResult = Record<string, unknown>>(db: NodePgDatabase<Record<string, unknown>>, options: CrossSchemaRawOptions): Promise<TResult[]>;
|
|
237
|
+
/**
|
|
238
|
+
* Create a typed cross-schema query using SQL template
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* const users = await crossSchemaSelect(tenantDb, {
|
|
243
|
+
* tenantSchema: 'tenant_abc',
|
|
244
|
+
* sharedSchema: 'public',
|
|
245
|
+
* select: {
|
|
246
|
+
* id: users.id,
|
|
247
|
+
* name: users.name,
|
|
248
|
+
* planName: plans.name,
|
|
249
|
+
* },
|
|
250
|
+
* from: { table: users, schema: 'tenant' },
|
|
251
|
+
* joins: [
|
|
252
|
+
* { table: plans, schema: 'shared', on: eq(users.planId, plans.id), type: 'left' },
|
|
253
|
+
* ],
|
|
254
|
+
* });
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
declare function buildCrossSchemaSelect<T extends Record<string, Column>>(fields: T, tenantSchema: string, _sharedSchema: string): {
|
|
258
|
+
columns: string[];
|
|
259
|
+
getSchema: () => string;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export { type ColumnSelection, type CrossSchemaContext, CrossSchemaQueryBuilder, type CrossSchemaRawOptions, type InferSelectedColumns, type JoinCondition, type JoinDefinition, type JoinType, type LookupResult, type QueryBuilderState, type SchemaSource, type SelectField, type SharedLookupConfig, type TableReference, buildCrossSchemaSelect, createCrossSchemaQuery, crossSchemaRaw, withSharedLookup };
|