drizzle-multitenant 1.0.10 → 1.2.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.
@@ -0,0 +1,824 @@
1
+ import { C as Config } from './types-BhK96FPC.js';
2
+ import { Pool } from 'pg';
3
+ import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
4
+
5
+ /**
6
+ * Table format for tracking migrations
7
+ * - "name": drizzle-multitenant native (filename-based)
8
+ * - "hash": SHA-256 hash with timestamp
9
+ * - "drizzle-kit": Exact drizzle-kit format (hash + bigint timestamp)
10
+ */
11
+ type TableFormat = 'name' | 'hash' | 'drizzle-kit';
12
+ /**
13
+ * Detected table format information
14
+ */
15
+ interface DetectedFormat {
16
+ /** The detected format type */
17
+ format: TableFormat;
18
+ /** The table name */
19
+ tableName: string;
20
+ /** Column configuration */
21
+ columns: {
22
+ /** Column used for identifying migrations */
23
+ identifier: 'name' | 'hash';
24
+ /** Column used for timestamp */
25
+ timestamp: 'applied_at' | 'created_at';
26
+ /** Data type of timestamp column */
27
+ timestampType: 'timestamp' | 'bigint';
28
+ };
29
+ }
30
+ /**
31
+ * Default format configuration for new tables
32
+ */
33
+ declare const DEFAULT_FORMAT: DetectedFormat;
34
+ /**
35
+ * drizzle-kit format configuration
36
+ */
37
+ declare const DRIZZLE_KIT_FORMAT: DetectedFormat;
38
+ /**
39
+ * Detect the format of an existing migrations table
40
+ *
41
+ * @param pool - Database connection pool
42
+ * @param schemaName - Schema to check
43
+ * @param tableName - Migrations table name
44
+ * @returns Detected format or null if table doesn't exist
45
+ */
46
+ declare function detectTableFormat(pool: Pool, schemaName: string, tableName: string): Promise<DetectedFormat | null>;
47
+ /**
48
+ * Get the format configuration for a specific format type
49
+ */
50
+ declare function getFormatConfig(format: TableFormat, tableName?: string): DetectedFormat;
51
+
52
+ /**
53
+ * Types for tenant cloning module
54
+ * @module clone/types
55
+ */
56
+
57
+ /**
58
+ * Value to use for anonymization (v1: null or fixed value)
59
+ */
60
+ type AnonymizeValue = null | string | number | boolean;
61
+ /**
62
+ * Anonymization rules by table and column
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const rules: AnonymizeRules = {
67
+ * users: {
68
+ * email: null,
69
+ * phone: null,
70
+ * ssn: '000-00-0000',
71
+ * },
72
+ * payments: {
73
+ * card_number: null,
74
+ * },
75
+ * };
76
+ * ```
77
+ */
78
+ interface AnonymizeRules {
79
+ [tableName: string]: {
80
+ [columnName: string]: AnonymizeValue;
81
+ };
82
+ }
83
+ /**
84
+ * Anonymization options
85
+ */
86
+ interface AnonymizeOptions {
87
+ /** Enable anonymization */
88
+ enabled: boolean;
89
+ /** Rules per table/column */
90
+ rules?: AnonymizeRules;
91
+ }
92
+ /**
93
+ * Options for cloning a tenant
94
+ */
95
+ interface CloneTenantOptions {
96
+ /** Include data (default: false, schema only) */
97
+ includeData?: boolean;
98
+ /** Anonymize sensitive data */
99
+ anonymize?: AnonymizeOptions;
100
+ /** Tables to exclude from cloning */
101
+ excludeTables?: string[];
102
+ /** Progress callback */
103
+ onProgress?: CloneProgressCallback;
104
+ /** Error handler */
105
+ onError?: (error: Error) => 'continue' | 'abort';
106
+ }
107
+ /**
108
+ * Progress status for cloning operation
109
+ */
110
+ type CloneProgressStatus = 'starting' | 'introspecting' | 'creating_schema' | 'creating_tables' | 'creating_indexes' | 'creating_constraints' | 'copying_data' | 'completed' | 'failed';
111
+ /**
112
+ * Progress callback for cloning
113
+ */
114
+ type CloneProgressCallback = (status: CloneProgressStatus, details?: {
115
+ table?: string;
116
+ progress?: number;
117
+ total?: number;
118
+ }) => void;
119
+ /**
120
+ * Result of cloning a tenant
121
+ */
122
+ interface CloneTenantResult {
123
+ /** Source tenant ID */
124
+ sourceTenant: string;
125
+ /** Target tenant ID */
126
+ targetTenant: string;
127
+ /** Target schema name */
128
+ targetSchema: string;
129
+ /** Whether the operation was successful */
130
+ success: boolean;
131
+ /** Error message if failed */
132
+ error?: string;
133
+ /** Tables cloned */
134
+ tables: string[];
135
+ /** Number of rows copied (if includeData) */
136
+ rowsCopied?: number;
137
+ /** Duration in milliseconds */
138
+ durationMs: number;
139
+ }
140
+ /**
141
+ * Configuration for Cloner
142
+ */
143
+ interface ClonerConfig {
144
+ /** Migrations table name (excluded from data copy) */
145
+ migrationsTable?: string;
146
+ }
147
+ /**
148
+ * Dependencies for Cloner
149
+ */
150
+ interface ClonerDependencies {
151
+ /** Create pool for specific schema */
152
+ createPool: (schemaName: string) => Promise<Pool>;
153
+ /** Create pool without schema (root) */
154
+ createRootPool: () => Promise<Pool>;
155
+ /** Schema name template function */
156
+ schemaNameTemplate: (tenantId: string) => string;
157
+ /** Check if schema exists */
158
+ schemaExists: (tenantId: string) => Promise<boolean>;
159
+ /** Create schema */
160
+ createSchema: (tenantId: string) => Promise<void>;
161
+ }
162
+
163
+ /**
164
+ * Seed function signature
165
+ * Called with the tenant database instance and tenant ID
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * const seed: SeedFunction = async (db, tenantId) => {
170
+ * await db.insert(roles).values([
171
+ * { name: 'admin', permissions: ['*'] },
172
+ * { name: 'user', permissions: ['read'] },
173
+ * ]);
174
+ * };
175
+ * ```
176
+ */
177
+ type SeedFunction<TSchema extends Record<string, unknown> = Record<string, unknown>> = (db: PostgresJsDatabase<TSchema>, tenantId: string) => Promise<void>;
178
+ /**
179
+ * Seed result for a single tenant
180
+ */
181
+ interface TenantSeedResult {
182
+ tenantId: string;
183
+ schemaName: string;
184
+ success: boolean;
185
+ error?: string;
186
+ durationMs: number;
187
+ }
188
+ /**
189
+ * Aggregate seed results
190
+ */
191
+ interface SeedResults {
192
+ total: number;
193
+ succeeded: number;
194
+ failed: number;
195
+ skipped: number;
196
+ details: TenantSeedResult[];
197
+ }
198
+ /**
199
+ * Options for seed operations
200
+ */
201
+ interface SeedOptions {
202
+ /** Number of concurrent seed operations */
203
+ concurrency?: number;
204
+ /** Progress callback */
205
+ onProgress?: (tenantId: string, status: 'starting' | 'seeding' | 'completed' | 'failed' | 'skipped') => void;
206
+ /** Error handler */
207
+ onError?: (tenantId: string, error: Error) => 'continue' | 'abort';
208
+ }
209
+ /**
210
+ * Migration file metadata
211
+ */
212
+ interface MigrationFile {
213
+ /** Migration file name */
214
+ name: string;
215
+ /** Full file path */
216
+ path: string;
217
+ /** SQL content */
218
+ sql: string;
219
+ /** Timestamp extracted from filename */
220
+ timestamp: number;
221
+ /** SHA-256 hash of file content (for drizzle-kit compatibility) */
222
+ hash: string;
223
+ }
224
+ /**
225
+ * Migration status for a tenant
226
+ */
227
+ interface TenantMigrationStatus {
228
+ tenantId: string;
229
+ schemaName: string;
230
+ appliedCount: number;
231
+ pendingCount: number;
232
+ pendingMigrations: string[];
233
+ status: 'ok' | 'behind' | 'error';
234
+ error?: string;
235
+ /** Detected table format (null for new tenants without migrations table) */
236
+ format: TableFormat | null;
237
+ }
238
+ /**
239
+ * Migration result for a single tenant
240
+ */
241
+ interface TenantMigrationResult {
242
+ tenantId: string;
243
+ schemaName: string;
244
+ success: boolean;
245
+ appliedMigrations: string[];
246
+ error?: string;
247
+ durationMs: number;
248
+ /** Table format used for this migration */
249
+ format?: TableFormat;
250
+ }
251
+ /**
252
+ * Aggregate migration results
253
+ */
254
+ interface MigrationResults {
255
+ total: number;
256
+ succeeded: number;
257
+ failed: number;
258
+ skipped: number;
259
+ details: TenantMigrationResult[];
260
+ }
261
+ /**
262
+ * Progress callback for migrations
263
+ */
264
+ type MigrationProgressCallback = (tenantId: string, status: 'starting' | 'migrating' | 'completed' | 'failed' | 'skipped', migrationName?: string) => void;
265
+ /**
266
+ * Error handler for migrations
267
+ */
268
+ type MigrationErrorHandler = (tenantId: string, error: Error) => 'continue' | 'abort';
269
+ /**
270
+ * Migration hooks
271
+ */
272
+ interface MigrationHooks {
273
+ /** Called before migrating a tenant */
274
+ beforeTenant?: (tenantId: string) => void | Promise<void>;
275
+ /** Called after migrating a tenant */
276
+ afterTenant?: (tenantId: string, result: TenantMigrationResult) => void | Promise<void>;
277
+ /** Called before applying a migration */
278
+ beforeMigration?: (tenantId: string, migrationName: string) => void | Promise<void>;
279
+ /** Called after applying a migration */
280
+ afterMigration?: (tenantId: string, migrationName: string, durationMs: number) => void | Promise<void>;
281
+ }
282
+ /**
283
+ * Migrator configuration
284
+ */
285
+ interface MigratorConfig {
286
+ /** Path to tenant migrations folder */
287
+ migrationsFolder: string;
288
+ /** Table name for tracking migrations */
289
+ migrationsTable?: string;
290
+ /** Function to discover tenant IDs */
291
+ tenantDiscovery: () => Promise<string[]>;
292
+ /** Migration hooks */
293
+ hooks?: MigrationHooks;
294
+ /**
295
+ * Table format for tracking migrations
296
+ * - "auto": Auto-detect existing format, use defaultFormat for new tables
297
+ * - "name": Use filename (drizzle-multitenant native)
298
+ * - "hash": Use SHA-256 hash
299
+ * - "drizzle-kit": Exact drizzle-kit format (hash + bigint timestamp)
300
+ * @default "auto"
301
+ */
302
+ tableFormat?: 'auto' | TableFormat;
303
+ /**
304
+ * When using "auto" format and no table exists, which format to create
305
+ * @default "name"
306
+ */
307
+ defaultFormat?: TableFormat;
308
+ }
309
+ /**
310
+ * Migrate options
311
+ */
312
+ interface MigrateOptions {
313
+ /** Number of concurrent migrations */
314
+ concurrency?: number;
315
+ /** Progress callback */
316
+ onProgress?: MigrationProgressCallback;
317
+ /** Error handler */
318
+ onError?: MigrationErrorHandler;
319
+ /** Dry run mode */
320
+ dryRun?: boolean;
321
+ }
322
+ /**
323
+ * Tenant creation options
324
+ */
325
+ interface CreateTenantOptions {
326
+ /** Apply all migrations after creating schema */
327
+ migrate?: boolean;
328
+ }
329
+ /**
330
+ * Tenant drop options
331
+ */
332
+ interface DropTenantOptions {
333
+ /** Skip confirmation (force drop) */
334
+ force?: boolean;
335
+ /** Cascade drop */
336
+ cascade?: boolean;
337
+ }
338
+ /**
339
+ * Applied migration record
340
+ */
341
+ interface AppliedMigration {
342
+ id: number;
343
+ /** Migration identifier (name or hash depending on format) */
344
+ identifier: string;
345
+ /** Migration name (only available in name-based format) */
346
+ name?: string;
347
+ /** Migration hash (only available in hash-based format) */
348
+ hash?: string;
349
+ appliedAt: Date;
350
+ }
351
+ /**
352
+ * Sync status for a single tenant
353
+ */
354
+ interface TenantSyncStatus {
355
+ tenantId: string;
356
+ schemaName: string;
357
+ /** Migrations in disk but not tracked in database */
358
+ missing: string[];
359
+ /** Migrations tracked in database but not found in disk */
360
+ orphans: string[];
361
+ /** Whether the tenant is in sync */
362
+ inSync: boolean;
363
+ /** Table format used */
364
+ format: TableFormat | null;
365
+ /** Error if any */
366
+ error?: string;
367
+ }
368
+ /**
369
+ * Aggregate sync status
370
+ */
371
+ interface SyncStatus {
372
+ total: number;
373
+ inSync: number;
374
+ outOfSync: number;
375
+ error: number;
376
+ details: TenantSyncStatus[];
377
+ }
378
+ /**
379
+ * Sync result for a single tenant
380
+ */
381
+ interface TenantSyncResult {
382
+ tenantId: string;
383
+ schemaName: string;
384
+ success: boolean;
385
+ /** Migrations that were marked as applied */
386
+ markedMigrations: string[];
387
+ /** Orphan records that were removed */
388
+ removedOrphans: string[];
389
+ error?: string;
390
+ durationMs: number;
391
+ }
392
+ /**
393
+ * Aggregate sync results
394
+ */
395
+ interface SyncResults {
396
+ total: number;
397
+ succeeded: number;
398
+ failed: number;
399
+ details: TenantSyncResult[];
400
+ }
401
+ /**
402
+ * Options for sync operations
403
+ */
404
+ interface SyncOptions {
405
+ /** Number of concurrent operations */
406
+ concurrency?: number;
407
+ /** Progress callback */
408
+ onProgress?: (tenantId: string, status: 'starting' | 'syncing' | 'completed' | 'failed') => void;
409
+ /** Error handler */
410
+ onError?: MigrationErrorHandler;
411
+ }
412
+ /**
413
+ * Column information from database introspection
414
+ */
415
+ interface ColumnInfo {
416
+ /** Column name */
417
+ name: string;
418
+ /** PostgreSQL data type */
419
+ dataType: string;
420
+ /** Full data type (e.g., varchar(255)) */
421
+ udtName: string;
422
+ /** Whether column is nullable */
423
+ isNullable: boolean;
424
+ /** Default value expression */
425
+ columnDefault: string | null;
426
+ /** Character maximum length for varchar/char */
427
+ characterMaximumLength: number | null;
428
+ /** Numeric precision for numeric types */
429
+ numericPrecision: number | null;
430
+ /** Numeric scale for numeric types */
431
+ numericScale: number | null;
432
+ /** Ordinal position in table */
433
+ ordinalPosition: number;
434
+ }
435
+ /**
436
+ * Index information from database introspection
437
+ */
438
+ interface IndexInfo {
439
+ /** Index name */
440
+ name: string;
441
+ /** Column names in the index */
442
+ columns: string[];
443
+ /** Whether index is unique */
444
+ isUnique: boolean;
445
+ /** Whether index is primary key */
446
+ isPrimary: boolean;
447
+ /** Index definition SQL */
448
+ definition: string;
449
+ }
450
+ /**
451
+ * Constraint information from database introspection
452
+ */
453
+ interface ConstraintInfo {
454
+ /** Constraint name */
455
+ name: string;
456
+ /** Constraint type (PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK) */
457
+ type: 'PRIMARY KEY' | 'FOREIGN KEY' | 'UNIQUE' | 'CHECK';
458
+ /** Columns involved in constraint */
459
+ columns: string[];
460
+ /** Foreign table (for foreign keys) */
461
+ foreignTable?: string;
462
+ /** Foreign columns (for foreign keys) */
463
+ foreignColumns?: string[];
464
+ /** Check expression (for check constraints) */
465
+ checkExpression?: string;
466
+ }
467
+ /**
468
+ * Table schema information
469
+ */
470
+ interface TableSchema {
471
+ /** Table name */
472
+ name: string;
473
+ /** Columns in the table */
474
+ columns: ColumnInfo[];
475
+ /** Indexes on the table */
476
+ indexes: IndexInfo[];
477
+ /** Constraints on the table */
478
+ constraints: ConstraintInfo[];
479
+ }
480
+ /**
481
+ * Full schema for a tenant
482
+ */
483
+ interface TenantSchema {
484
+ /** Tenant ID */
485
+ tenantId: string;
486
+ /** Schema name */
487
+ schemaName: string;
488
+ /** Tables in the schema */
489
+ tables: TableSchema[];
490
+ /** Introspection timestamp */
491
+ introspectedAt: Date;
492
+ }
493
+ /**
494
+ * Column drift details
495
+ */
496
+ interface ColumnDrift {
497
+ /** Column name */
498
+ column: string;
499
+ /** Type of drift */
500
+ type: 'missing' | 'extra' | 'type_mismatch' | 'nullable_mismatch' | 'default_mismatch';
501
+ /** Expected value (from reference) */
502
+ expected?: string | boolean | null;
503
+ /** Actual value (from tenant) */
504
+ actual?: string | boolean | null;
505
+ /** Human-readable description */
506
+ description: string;
507
+ }
508
+ /**
509
+ * Index drift details
510
+ */
511
+ interface IndexDrift {
512
+ /** Index name */
513
+ index: string;
514
+ /** Type of drift */
515
+ type: 'missing' | 'extra' | 'definition_mismatch';
516
+ /** Expected definition */
517
+ expected?: string;
518
+ /** Actual definition */
519
+ actual?: string;
520
+ /** Human-readable description */
521
+ description: string;
522
+ }
523
+ /**
524
+ * Constraint drift details
525
+ */
526
+ interface ConstraintDrift {
527
+ /** Constraint name */
528
+ constraint: string;
529
+ /** Type of drift */
530
+ type: 'missing' | 'extra' | 'definition_mismatch';
531
+ /** Expected details */
532
+ expected?: string;
533
+ /** Actual details */
534
+ actual?: string;
535
+ /** Human-readable description */
536
+ description: string;
537
+ }
538
+ /**
539
+ * Table drift details
540
+ */
541
+ interface TableDrift {
542
+ /** Table name */
543
+ table: string;
544
+ /** Whether the entire table is missing or extra */
545
+ status: 'ok' | 'missing' | 'extra' | 'drifted';
546
+ /** Column drifts */
547
+ columns: ColumnDrift[];
548
+ /** Index drifts */
549
+ indexes: IndexDrift[];
550
+ /** Constraints drifts */
551
+ constraints: ConstraintDrift[];
552
+ }
553
+ /**
554
+ * Schema drift for a single tenant
555
+ */
556
+ interface TenantSchemaDrift {
557
+ /** Tenant ID */
558
+ tenantId: string;
559
+ /** Schema name */
560
+ schemaName: string;
561
+ /** Whether schema has drift */
562
+ hasDrift: boolean;
563
+ /** Table-level drifts */
564
+ tables: TableDrift[];
565
+ /** Total number of issues */
566
+ issueCount: number;
567
+ /** Error if introspection failed */
568
+ error?: string;
569
+ }
570
+ /**
571
+ * Aggregate schema drift status
572
+ */
573
+ interface SchemaDriftStatus {
574
+ /** Reference tenant used for comparison */
575
+ referenceTenant: string;
576
+ /** Total tenants checked */
577
+ total: number;
578
+ /** Tenants without drift */
579
+ noDrift: number;
580
+ /** Tenants with drift */
581
+ withDrift: number;
582
+ /** Tenants with errors */
583
+ error: number;
584
+ /** Detailed results per tenant */
585
+ details: TenantSchemaDrift[];
586
+ /** Timestamp of the check */
587
+ timestamp: string;
588
+ /** Duration of the check in ms */
589
+ durationMs: number;
590
+ }
591
+ /**
592
+ * Options for schema drift detection
593
+ */
594
+ interface SchemaDriftOptions {
595
+ /** Tenant ID to use as reference (default: first tenant) */
596
+ referenceTenant?: string;
597
+ /** Specific tenant IDs to check (default: all tenants) */
598
+ tenantIds?: string[];
599
+ /** Number of concurrent checks */
600
+ concurrency?: number;
601
+ /** Whether to include index comparison */
602
+ includeIndexes?: boolean;
603
+ /** Whether to include constraint comparison */
604
+ includeConstraints?: boolean;
605
+ /** Tables to exclude from comparison */
606
+ excludeTables?: string[];
607
+ /** Progress callback */
608
+ onProgress?: (tenantId: string, status: 'starting' | 'introspecting' | 'comparing' | 'completed' | 'failed') => void;
609
+ }
610
+
611
+ /**
612
+ * Parallel migration engine for multi-tenant applications
613
+ */
614
+ declare class Migrator<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown>> {
615
+ private readonly migratorConfig;
616
+ private readonly migrationsTable;
617
+ private readonly schemaManager;
618
+ private readonly driftDetector;
619
+ private readonly seeder;
620
+ private readonly syncManager;
621
+ private readonly migrationExecutor;
622
+ private readonly batchExecutor;
623
+ private readonly cloner;
624
+ constructor(tenantConfig: Config<TTenantSchema, TSharedSchema>, migratorConfig: MigratorConfig);
625
+ /**
626
+ * Migrate all tenants in parallel
627
+ *
628
+ * Delegates to BatchExecutor for parallel migration operations.
629
+ */
630
+ migrateAll(options?: MigrateOptions): Promise<MigrationResults>;
631
+ /**
632
+ * Migrate a single tenant
633
+ *
634
+ * Delegates to MigrationExecutor for single tenant operations.
635
+ */
636
+ migrateTenant(tenantId: string, migrations?: MigrationFile[], options?: {
637
+ dryRun?: boolean;
638
+ onProgress?: MigrateOptions['onProgress'];
639
+ }): Promise<TenantMigrationResult>;
640
+ /**
641
+ * Migrate specific tenants
642
+ *
643
+ * Delegates to BatchExecutor for parallel migration operations.
644
+ */
645
+ migrateTenants(tenantIds: string[], options?: MigrateOptions): Promise<MigrationResults>;
646
+ /**
647
+ * Get migration status for all tenants
648
+ *
649
+ * Delegates to BatchExecutor for status operations.
650
+ */
651
+ getStatus(): Promise<TenantMigrationStatus[]>;
652
+ /**
653
+ * Get migration status for a specific tenant
654
+ *
655
+ * Delegates to MigrationExecutor for single tenant operations.
656
+ */
657
+ getTenantStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantMigrationStatus>;
658
+ /**
659
+ * Create a new tenant schema and optionally apply migrations
660
+ */
661
+ createTenant(tenantId: string, options?: CreateTenantOptions): Promise<void>;
662
+ /**
663
+ * Drop a tenant schema
664
+ */
665
+ dropTenant(tenantId: string, options?: DropTenantOptions): Promise<void>;
666
+ /**
667
+ * Check if a tenant schema exists
668
+ */
669
+ tenantExists(tenantId: string): Promise<boolean>;
670
+ /**
671
+ * Clone a tenant to a new tenant
672
+ *
673
+ * By default, clones only schema structure. Use includeData to copy data.
674
+ *
675
+ * @example
676
+ * ```typescript
677
+ * // Schema-only clone
678
+ * await migrator.cloneTenant('production', 'dev');
679
+ *
680
+ * // Clone with data
681
+ * await migrator.cloneTenant('production', 'dev', { includeData: true });
682
+ *
683
+ * // Clone with anonymization
684
+ * await migrator.cloneTenant('production', 'dev', {
685
+ * includeData: true,
686
+ * anonymize: {
687
+ * enabled: true,
688
+ * rules: {
689
+ * users: { email: null, phone: null },
690
+ * },
691
+ * },
692
+ * });
693
+ * ```
694
+ */
695
+ cloneTenant(sourceTenantId: string, targetTenantId: string, options?: CloneTenantOptions): Promise<CloneTenantResult>;
696
+ /**
697
+ * Mark migrations as applied without executing SQL
698
+ * Useful for syncing tracking state with already-applied migrations
699
+ *
700
+ * Delegates to MigrationExecutor for single tenant operations.
701
+ */
702
+ markAsApplied(tenantId: string, options?: {
703
+ onProgress?: MigrateOptions['onProgress'];
704
+ }): Promise<TenantMigrationResult>;
705
+ /**
706
+ * Mark migrations as applied for all tenants without executing SQL
707
+ * Useful for syncing tracking state with already-applied migrations
708
+ *
709
+ * Delegates to BatchExecutor for parallel operations.
710
+ */
711
+ markAllAsApplied(options?: MigrateOptions): Promise<MigrationResults>;
712
+ /**
713
+ * Get sync status for all tenants
714
+ * Detects divergences between migrations on disk and tracking in database
715
+ */
716
+ getSyncStatus(): Promise<SyncStatus>;
717
+ /**
718
+ * Get sync status for a specific tenant
719
+ */
720
+ getTenantSyncStatus(tenantId: string, migrations?: MigrationFile[]): Promise<TenantSyncStatus>;
721
+ /**
722
+ * Mark missing migrations as applied for a tenant
723
+ */
724
+ markMissing(tenantId: string): Promise<TenantSyncResult>;
725
+ /**
726
+ * Mark missing migrations as applied for all tenants
727
+ */
728
+ markAllMissing(options?: SyncOptions): Promise<SyncResults>;
729
+ /**
730
+ * Remove orphan migration records for a tenant
731
+ */
732
+ cleanOrphans(tenantId: string): Promise<TenantSyncResult>;
733
+ /**
734
+ * Remove orphan migration records for all tenants
735
+ */
736
+ cleanAllOrphans(options?: SyncOptions): Promise<SyncResults>;
737
+ /**
738
+ * Seed a single tenant with initial data
739
+ *
740
+ * @example
741
+ * ```typescript
742
+ * const seed: SeedFunction = async (db, tenantId) => {
743
+ * await db.insert(roles).values([
744
+ * { name: 'admin', permissions: ['*'] },
745
+ * { name: 'user', permissions: ['read'] },
746
+ * ]);
747
+ * };
748
+ *
749
+ * await migrator.seedTenant('tenant-123', seed);
750
+ * ```
751
+ */
752
+ seedTenant(tenantId: string, seedFn: SeedFunction<TTenantSchema>): Promise<TenantSeedResult>;
753
+ /**
754
+ * Seed all tenants with initial data in parallel
755
+ *
756
+ * @example
757
+ * ```typescript
758
+ * const seed: SeedFunction = async (db, tenantId) => {
759
+ * await db.insert(roles).values([
760
+ * { name: 'admin', permissions: ['*'] },
761
+ * ]);
762
+ * };
763
+ *
764
+ * await migrator.seedAll(seed, { concurrency: 10 });
765
+ * ```
766
+ */
767
+ seedAll(seedFn: SeedFunction<TTenantSchema>, options?: SeedOptions): Promise<SeedResults>;
768
+ /**
769
+ * Seed specific tenants with initial data
770
+ */
771
+ seedTenants(tenantIds: string[], seedFn: SeedFunction<TTenantSchema>, options?: SeedOptions): Promise<SeedResults>;
772
+ /**
773
+ * Load migration files from the migrations folder
774
+ */
775
+ private loadMigrations;
776
+ /**
777
+ * Get or detect the format for a schema
778
+ * Returns the configured format or auto-detects from existing table
779
+ *
780
+ * Note: This method is shared with SyncManager and MigrationExecutor via dependency injection.
781
+ */
782
+ private getOrDetectFormat;
783
+ /**
784
+ * Detect schema drift across all tenants
785
+ * Compares each tenant's schema against a reference tenant (first tenant by default)
786
+ *
787
+ * @example
788
+ * ```typescript
789
+ * const drift = await migrator.getSchemaDrift();
790
+ * if (drift.withDrift > 0) {
791
+ * console.log('Schema drift detected!');
792
+ * for (const tenant of drift.details) {
793
+ * if (tenant.hasDrift) {
794
+ * console.log(`Tenant ${tenant.tenantId} has drift:`);
795
+ * for (const table of tenant.tables) {
796
+ * for (const col of table.columns) {
797
+ * console.log(` - ${table.table}.${col.column}: ${col.description}`);
798
+ * }
799
+ * }
800
+ * }
801
+ * }
802
+ * }
803
+ * ```
804
+ */
805
+ getSchemaDrift(options?: SchemaDriftOptions): Promise<SchemaDriftStatus>;
806
+ /**
807
+ * Get schema drift for a specific tenant compared to a reference
808
+ */
809
+ getTenantSchemaDrift(tenantId: string, referenceTenantId: string, options?: Pick<SchemaDriftOptions, 'includeIndexes' | 'includeConstraints' | 'excludeTables'>): Promise<TenantSchemaDrift>;
810
+ /**
811
+ * Introspect the schema of a tenant
812
+ */
813
+ introspectTenantSchema(tenantId: string, options?: {
814
+ includeIndexes?: boolean;
815
+ includeConstraints?: boolean;
816
+ excludeTables?: string[];
817
+ }): Promise<TenantSchema | null>;
818
+ }
819
+ /**
820
+ * Create a migrator instance
821
+ */
822
+ declare function createMigrator<TTenantSchema extends Record<string, unknown>, TSharedSchema extends Record<string, unknown>>(tenantConfig: Config<TTenantSchema, TSharedSchema>, migratorConfig: MigratorConfig): Migrator<TTenantSchema, TSharedSchema>;
823
+
824
+ export { type AppliedMigration as A, type TableFormat as B, type CreateTenantOptions as C, type DropTenantOptions as D, type ColumnInfo as E, type ConstraintInfo as F, type TableSchema as G, type TenantSchema as H, type IndexInfo as I, type ColumnDrift as J, type IndexDrift as K, type ConstraintDrift as L, Migrator as M, type TableDrift as N, type TenantSchemaDrift as O, type SchemaDriftStatus as P, type SchemaDriftOptions as Q, type CloneProgressCallback as R, type SeedFunction as S, type TenantMigrationResult as T, type CloneProgressStatus as U, type AnonymizeOptions as V, type AnonymizeRules as W, type AnonymizeValue as X, type MigratorConfig as a, type MigrationFile as b, createMigrator as c, type MigrateOptions as d, type MigrationResults as e, type TenantMigrationStatus as f, type MigrationHooks as g, type MigrationProgressCallback as h, type MigrationErrorHandler as i, type SeedOptions as j, type TenantSeedResult as k, type SeedResults as l, type DetectedFormat as m, type SyncStatus as n, type TenantSyncStatus as o, type TenantSyncResult as p, type SyncOptions as q, type SyncResults as r, type ClonerConfig as s, type ClonerDependencies as t, type CloneTenantOptions as u, type CloneTenantResult as v, detectTableFormat as w, getFormatConfig as x, DEFAULT_FORMAT as y, DRIZZLE_KIT_FORMAT as z };