@magnet-cms/adapter-db-drizzle 1.0.2

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,1059 @@
1
+ import { SchemaOptions, PropOptions, DatabaseAdapter, AdapterName, DBConfig, AdapterFeature, AdapterCapabilities, EnvVarRequirement, DatabaseMagnetProvider, QueryBuilder, FilterQuery, SortQuery, ProjectionQuery, BaseSchema, PaginatedResult } from '@magnet-cms/common';
2
+ import { Type, DynamicModule } from '@nestjs/common';
3
+ import { pgTable, PgDatabase, PgQueryResultHKT, PgTable } from 'drizzle-orm/pg-core';
4
+ import { NodePgDatabase } from 'drizzle-orm/node-postgres';
5
+
6
+ /**
7
+ * Drizzle-specific Schema decorator.
8
+ * Stores metadata that will be used to generate Drizzle table schemas.
9
+ *
10
+ * This is called by the common @Schema() decorator after detecting
11
+ * that Drizzle is the active database adapter.
12
+ */
13
+ declare function Schema(options?: SchemaOptions): ClassDecorator;
14
+ /**
15
+ * Get Drizzle schema metadata from a class
16
+ */
17
+ declare function getDrizzleSchemaMetadata(target: Function): {
18
+ name: string;
19
+ tableName: string;
20
+ i18n: boolean;
21
+ versioning: boolean;
22
+ } | null;
23
+
24
+ /**
25
+ * Drizzle-specific Prop decorator.
26
+ * Stores property metadata that will be used to generate Drizzle column definitions.
27
+ *
28
+ * This is called by the common @Prop() decorator after detecting
29
+ * that Drizzle is the active database adapter.
30
+ */
31
+ declare function Prop(options?: PropOptions): PropertyDecorator;
32
+ /**
33
+ * Get Drizzle property metadata from a class
34
+ */
35
+ declare function getDrizzlePropsMetadata(target: Function): Map<string | symbol, PropOptions>;
36
+
37
+ declare function InjectModel(schema: Type): ParameterDecorator;
38
+
39
+ /**
40
+ * Get or generate a Drizzle table schema from a class
41
+ */
42
+ declare function getOrGenerateSchema(schemaClass: Type): {
43
+ table: ReturnType<typeof pgTable>;
44
+ tableName: string;
45
+ };
46
+ /**
47
+ * Generate a Drizzle table schema from a decorated class
48
+ */
49
+ declare function generateSchema(schemaClass: Type): {
50
+ table: ReturnType<typeof pgTable>;
51
+ tableName: string;
52
+ };
53
+ /**
54
+ * Get all registered schemas (read-only view of the registry)
55
+ */
56
+ declare function getRegisteredSchemas(): ReadonlyMap<string, {
57
+ table: ReturnType<typeof pgTable>;
58
+ tableName: string;
59
+ }>;
60
+ /**
61
+ * Clear the schema registry (useful for testing)
62
+ */
63
+ declare function clearSchemaRegistry(): void;
64
+
65
+ /**
66
+ * Options for document columns
67
+ */
68
+ interface DocumentColumnOptions {
69
+ /** Whether i18n is enabled */
70
+ hasI18n: boolean;
71
+ /** Whether versioning is enabled */
72
+ hasVersioning: boolean;
73
+ }
74
+ /**
75
+ * Document status enum values
76
+ */
77
+ declare const DOCUMENT_STATUS: {
78
+ readonly DRAFT: "draft";
79
+ readonly PUBLISHED: "published";
80
+ readonly ARCHIVED: "archived";
81
+ };
82
+ type DocumentStatus = (typeof DOCUMENT_STATUS)[keyof typeof DOCUMENT_STATUS];
83
+ /**
84
+ * Default locale
85
+ */
86
+ declare const DEFAULT_LOCALE = "en";
87
+ /**
88
+ * Apply document columns for i18n and versioning support.
89
+ * This mirrors the Mongoose document plugin behavior.
90
+ *
91
+ * Adds the following columns:
92
+ * - documentId: Groups all locale variants and versions of the same logical document
93
+ * - locale: The locale of this document variant (e.g., 'en', 'pt-BR')
94
+ * - status: The status of this document ('draft', 'published', 'archived')
95
+ * - publishedAt: When this document was published (if applicable)
96
+ */
97
+ declare function applyDocumentColumns(options: DocumentColumnOptions): Record<string, any>;
98
+ /**
99
+ * Check if a record is a draft
100
+ */
101
+ declare function isDraft(record: {
102
+ status?: string;
103
+ }): boolean;
104
+ /**
105
+ * Check if a record is published
106
+ */
107
+ declare function isPublished(record: {
108
+ status?: string;
109
+ }): boolean;
110
+
111
+ /**
112
+ * Supported SQL dialects for migrations
113
+ */
114
+ type MigrationDialect = 'postgresql' | 'mysql' | 'sqlite';
115
+ /**
116
+ * Migration mode:
117
+ * - 'auto': Auto-generate and apply migrations on startup (development)
118
+ * - 'manual': Only apply migrations via CLI (production)
119
+ */
120
+ type MigrationMode = 'auto' | 'manual';
121
+ /**
122
+ * Configuration for the migration system
123
+ */
124
+ interface MigrationConfig {
125
+ /**
126
+ * Migration mode — 'auto' for development, 'manual' for production
127
+ * @default 'auto'
128
+ */
129
+ mode: MigrationMode;
130
+ /**
131
+ * Directory where migration files are stored
132
+ * @default './migrations'
133
+ */
134
+ directory: string;
135
+ /**
136
+ * Table name for tracking applied migrations
137
+ * @default '_magnet_migrations'
138
+ */
139
+ tableName: string;
140
+ /**
141
+ * Table name for migration lock
142
+ * @default '_magnet_migrations_lock'
143
+ */
144
+ lockTableName: string;
145
+ /**
146
+ * Timeout for acquiring migration lock (ms)
147
+ * @default 30000
148
+ */
149
+ lockTimeout: number;
150
+ /**
151
+ * Whether to run each migration in a transaction
152
+ * @default true
153
+ */
154
+ transactional: boolean;
155
+ }
156
+ /**
157
+ * Default migration configuration
158
+ */
159
+ declare const DEFAULT_MIGRATION_CONFIG: MigrationConfig;
160
+ /**
161
+ * A database connection used to execute migration SQL.
162
+ * Accept any object with an execute method for maximum compatibility.
163
+ */
164
+ interface MigrationDb {
165
+ execute(sql: string, params?: unknown[]): Promise<unknown>;
166
+ }
167
+ /**
168
+ * A single migration with up and down functions
169
+ */
170
+ interface Migration {
171
+ /** Unique identifier (usually filename without extension) */
172
+ id: string;
173
+ /** Unix timestamp when migration was created */
174
+ timestamp: number;
175
+ /** Human-readable description */
176
+ description?: string;
177
+ /** Flag for dangerous operations (drops, type changes) */
178
+ dangerous?: boolean;
179
+ /** Warning messages for dangerous operations */
180
+ warnings?: string[];
181
+ /** Apply the migration */
182
+ up(db: MigrationDb): Promise<void>;
183
+ /** Revert the migration */
184
+ down(db: MigrationDb): Promise<void>;
185
+ }
186
+ /**
187
+ * Record of an applied migration stored in the history table
188
+ */
189
+ interface MigrationHistoryRecord {
190
+ /** Migration ID */
191
+ id: string;
192
+ /** Migration name (same as id) */
193
+ name: string;
194
+ /** Unix timestamp when migration was created */
195
+ timestamp: number;
196
+ /** When this migration was applied */
197
+ appliedAt: Date;
198
+ /** Checksum of the migration functions at time of application */
199
+ checksum: string;
200
+ }
201
+ /**
202
+ * Column change descriptor for diffing
203
+ */
204
+ interface ColumnChange {
205
+ /** Table name */
206
+ table: string;
207
+ /** Column name */
208
+ column: string;
209
+ /** SQL type */
210
+ type?: string;
211
+ /** Whether column is nullable */
212
+ nullable?: boolean;
213
+ /** Default value */
214
+ default?: string;
215
+ /** Old column name (for renames) */
216
+ oldColumn?: string;
217
+ /** Old type (for type changes) */
218
+ oldType?: string;
219
+ }
220
+ /**
221
+ * Index descriptor for diffing
222
+ */
223
+ interface IndexChange {
224
+ /** Index name */
225
+ name: string;
226
+ /** Table name */
227
+ table: string;
228
+ /** Column names */
229
+ columns: string[];
230
+ /** Whether unique */
231
+ unique?: boolean;
232
+ }
233
+ /**
234
+ * Result of comparing decorator schemas against database state
235
+ */
236
+ interface DiffResult {
237
+ /** Tables to create */
238
+ tablesToCreate: TableDefinition[];
239
+ /** Table names to drop */
240
+ tablesToDrop: string[];
241
+ /** Columns to add */
242
+ columnsToAdd: ColumnChange[];
243
+ /** Columns to remove */
244
+ columnsToRemove: ColumnChange[];
245
+ /** Columns to alter (type/nullable/default changes) */
246
+ columnsToAlter: ColumnChange[];
247
+ /** Indexes to add */
248
+ indexesToAdd: IndexChange[];
249
+ /** Index names to remove */
250
+ indexesToRemove: string[];
251
+ /** Whether there are no changes */
252
+ isEmpty: boolean;
253
+ }
254
+ /**
255
+ * Full table definition for CREATE TABLE
256
+ */
257
+ interface TableDefinition {
258
+ /** Table name */
259
+ name: string;
260
+ /** Column definitions */
261
+ columns: ColumnChange[];
262
+ /** Index definitions */
263
+ indexes: IndexChange[];
264
+ }
265
+ /**
266
+ * Result of running migrations
267
+ */
268
+ interface MigrationResult {
269
+ /** Number of migrations applied */
270
+ applied: number;
271
+ /** Names of applied migrations */
272
+ names: string[];
273
+ /** Time taken per migration in ms */
274
+ timings: Record<string, number>;
275
+ }
276
+ /**
277
+ * Base migration error
278
+ */
279
+ declare class MigrationError extends Error {
280
+ readonly migrationId: string;
281
+ readonly cause?: Error | undefined;
282
+ constructor(message: string, migrationId: string, cause?: Error | undefined);
283
+ }
284
+ /**
285
+ * Thrown when the migration lock cannot be acquired
286
+ */
287
+ declare class MigrationLockError extends MigrationError {
288
+ constructor(migrationId?: string);
289
+ }
290
+ /**
291
+ * Thrown when a migration file's checksum differs from what was recorded
292
+ */
293
+ declare class MigrationChecksumError extends MigrationError {
294
+ constructor(migrationId: string, expected: string, actual: string);
295
+ }
296
+
297
+ /**
298
+ * Drizzle configuration for MagnetModuleOptions
299
+ */
300
+ interface DrizzleConfig {
301
+ /** Database connection string */
302
+ connectionString: string;
303
+ /** SQL dialect to use */
304
+ dialect: 'postgresql' | 'mysql' | 'sqlite';
305
+ /** Database driver to use (auto-detected if not specified) */
306
+ driver?: 'pg' | 'neon' | 'mysql2' | 'better-sqlite3';
307
+ /** Enable debug logging */
308
+ debug?: boolean;
309
+ /**
310
+ * Migration configuration. If omitted, falls back to legacy CREATE TABLE IF NOT EXISTS behavior.
311
+ */
312
+ migrations?: Partial<MigrationConfig>;
313
+ }
314
+ /**
315
+ * Supported Drizzle database types.
316
+ * MySQL and SQLite connections are cast to this type at runtime for API compatibility.
317
+ */
318
+ type DrizzleDB = NodePgDatabase | PgDatabase<PgQueryResultHKT, Record<string, never>>;
319
+ /**
320
+ * Schema metadata stored via decorators
321
+ */
322
+ interface SchemaMetadata {
323
+ /** Schema class name */
324
+ name: string;
325
+ /** Whether i18n is enabled (default: true) */
326
+ i18n?: boolean;
327
+ /** Whether versioning is enabled (default: false) */
328
+ versioning?: boolean;
329
+ /** Table name (defaults to lowercase pluralized class name) */
330
+ tableName?: string;
331
+ }
332
+ /**
333
+ * Property metadata stored via decorators
334
+ */
335
+ interface PropMetadata {
336
+ /** Property name */
337
+ name: string;
338
+ /** Property type */
339
+ type?: any;
340
+ /** Whether the property is required */
341
+ required?: boolean;
342
+ /** Whether the property is unique */
343
+ unique?: boolean;
344
+ /** Default value */
345
+ default?: any;
346
+ /** Whether the property is nullable */
347
+ nullable?: boolean;
348
+ /** Whether the property supports i18n */
349
+ intl?: boolean;
350
+ /** Whether the property is hidden from API responses */
351
+ hidden?: boolean;
352
+ /** Whether the property is readonly */
353
+ readonly?: boolean;
354
+ /** Reference to another schema (for relationships) */
355
+ ref?: string;
356
+ /** Description for documentation */
357
+ description?: string;
358
+ }
359
+ /**
360
+ * Generated Drizzle table schema
361
+ */
362
+ interface GeneratedSchema {
363
+ /** The Drizzle table definition */
364
+ table: any;
365
+ /** The schema class reference */
366
+ schemaClass: any;
367
+ /** Schema metadata */
368
+ metadata: SchemaMetadata;
369
+ /** Property metadata map */
370
+ properties: Map<string, PropMetadata>;
371
+ }
372
+ /**
373
+ * Drizzle module options for NestJS dynamic module
374
+ */
375
+ interface DrizzleModuleOptions {
376
+ /** Drizzle database instance */
377
+ db: DrizzleDB;
378
+ /** Configuration */
379
+ config: DrizzleConfig;
380
+ }
381
+
382
+ /**
383
+ * Create a Neon serverless database connection.
384
+ * Uses @neondatabase/serverless for edge/serverless deployments.
385
+ *
386
+ * @example
387
+ * ```typescript
388
+ * const db = await createNeonConnection({
389
+ * connectionString: process.env.DATABASE_URL,
390
+ * dialect: 'postgresql',
391
+ * driver: 'neon',
392
+ * })
393
+ * ```
394
+ */
395
+ declare function createNeonConnection(config: DrizzleConfig): Promise<{
396
+ db: any;
397
+ pool: null;
398
+ }>;
399
+ /**
400
+ * Create a Neon WebSocket connection for pooled/session mode.
401
+ * Better for long-running processes with connection pooling.
402
+ */
403
+ declare function createNeonWebSocketConnection(config: DrizzleConfig): Promise<{
404
+ db: any;
405
+ pool: any;
406
+ }>;
407
+
408
+ /**
409
+ * Injection tokens
410
+ */
411
+ declare const DRIZZLE_DB = "DRIZZLE_DB";
412
+ declare const DRIZZLE_CONFIG = "DRIZZLE_CONFIG";
413
+ /**
414
+ * Get model token for a schema
415
+ * @deprecated Use getModelToken from @magnet-cms/common instead
416
+ */
417
+ declare function getDrizzleModelToken(schema: string): string;
418
+ /**
419
+ * Drizzle ORM adapter for Magnet CMS.
420
+ * Supports PostgreSQL, MySQL, and SQLite through Drizzle ORM.
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * MagnetModule.forRoot([
425
+ * DrizzleDatabaseAdapter.forRoot({ dialect: 'postgresql' }),
426
+ * ])
427
+ * ```
428
+ */
429
+ declare class DrizzleDatabaseAdapter extends DatabaseAdapter {
430
+ readonly name: AdapterName;
431
+ private db;
432
+ private pool;
433
+ private options;
434
+ private schemaRegistry;
435
+ private tablesInitialized;
436
+ /**
437
+ * Automatically create tables for all registered schemas.
438
+ * Called lazily when first model is accessed, or can be called explicitly.
439
+ */
440
+ ensureTablesCreated(): Promise<void>;
441
+ /**
442
+ * Run the auto-migration system when `config.migrations` is configured.
443
+ */
444
+ private runAutoMigration;
445
+ /**
446
+ * Create tables for all registered schemas in the database.
447
+ * Uses Drizzle's getTableConfig to generate CREATE TABLE IF NOT EXISTS statements.
448
+ */
449
+ private createTables;
450
+ /**
451
+ * Quote identifier for the given dialect.
452
+ */
453
+ private quoteIdent;
454
+ /**
455
+ * Generate and execute CREATE TABLE IF NOT EXISTS statement from table config.
456
+ */
457
+ private createTableFromConfig;
458
+ /**
459
+ * Map PostgreSQL SQL types to dialect-specific types.
460
+ */
461
+ private mapSQLTypeForDialect;
462
+ /**
463
+ * Infer SQL type from column definition when getSQLType() is not available.
464
+ */
465
+ private inferSQLType;
466
+ /**
467
+ * Format default value for SQL DEFAULT clause.
468
+ */
469
+ private formatDefaultValue;
470
+ /**
471
+ * Connect to the database and return a NestJS dynamic module.
472
+ * Supports both synchronous (pg) and asynchronous (neon) drivers.
473
+ */
474
+ connect(config: DBConfig): DynamicModule;
475
+ /**
476
+ * Register schemas and return a NestJS dynamic module with model providers.
477
+ * Note: Providers return raw { db, table, schemaClass } for the model() method to wrap.
478
+ */
479
+ forFeature(schemas: Type | Type[]): DynamicModule;
480
+ /**
481
+ * Create a Model class from raw model data or a factory (for lazy init).
482
+ * Core's DatabaseModule passes an async factory; we support both.
483
+ */
484
+ model<T>(modelDataOrFactory: {
485
+ db: DrizzleDB;
486
+ table: PgTable;
487
+ schemaClass: Type;
488
+ } | (() => Promise<{
489
+ db: DrizzleDB;
490
+ table: PgTable;
491
+ schemaClass: Type;
492
+ }>)): any;
493
+ /**
494
+ * Create a model class that lazily resolves the factory (used by core's DatabaseModule).
495
+ */
496
+ private createLazyModel;
497
+ /**
498
+ * Get the injection token for a schema.
499
+ */
500
+ token(schema: string): string;
501
+ /**
502
+ * Get the database instance (for advanced usage).
503
+ */
504
+ getDb(): DrizzleDB | null;
505
+ /**
506
+ * Check if adapter supports a feature
507
+ */
508
+ supports(feature: AdapterFeature): boolean;
509
+ /**
510
+ * Get adapter capabilities
511
+ */
512
+ getCapabilities(): AdapterCapabilities;
513
+ /**
514
+ * Create database connection based on config (synchronous, for pg/mysql/sqlite drivers).
515
+ */
516
+ private createConnection;
517
+ /**
518
+ * Create database connection asynchronously (required for Neon driver).
519
+ */
520
+ private createConnectionAsync;
521
+ /**
522
+ * Graceful shutdown - close database connections.
523
+ */
524
+ onModuleDestroy(): Promise<void>;
525
+ /** Environment variables required by this adapter */
526
+ static readonly envVars: EnvVarRequirement[];
527
+ /**
528
+ * Create a configured database provider for MagnetModule.forRoot().
529
+ * Auto-resolves the connection string from DATABASE_URL env var if not provided.
530
+ *
531
+ * @param config - Optional Drizzle configuration. If omitted, reads from DATABASE_URL env var.
532
+ * @returns A DatabaseMagnetProvider to pass to MagnetModule.forRoot()
533
+ */
534
+ static forRoot(config?: Partial<DrizzleConfig>): DatabaseMagnetProvider;
535
+ /**
536
+ * Get the singleton adapter instance.
537
+ * @internal Used by DatabaseModule for forFeature() calls.
538
+ */
539
+ static getInstance(): DrizzleDatabaseAdapter;
540
+ }
541
+ /**
542
+ * @deprecated Use DrizzleDatabaseAdapter instead.
543
+ * Kept temporarily for internal compatibility during migration.
544
+ */
545
+ declare const Adapter: DrizzleDatabaseAdapter;
546
+
547
+ /**
548
+ * Drizzle implementation of QueryBuilder for fluent database queries.
549
+ * Provides chainable methods for filtering, sorting, pagination, and projection.
550
+ *
551
+ * @example
552
+ * ```typescript
553
+ * const users = await userModel.query()
554
+ * .where({ status: 'active', age: { $gte: 18 } })
555
+ * .sort({ createdAt: -1 })
556
+ * .limit(10)
557
+ * .skip(20)
558
+ * .exec()
559
+ * ```
560
+ */
561
+ /**
562
+ * Lazy query builder that buffers chainable operations synchronously
563
+ * and replays them on the real DrizzleQueryBuilder when a terminal
564
+ * method (exec, execOne, count, exists, paginate) is called.
565
+ *
566
+ * This solves the problem where LazyDrizzleModelAdapter.query() needs
567
+ * to return a synchronous, chainable object even though the underlying
568
+ * model requires async initialization.
569
+ */
570
+ declare class LazyQueryBuilder<T> extends QueryBuilder<T> {
571
+ private readonly factory;
572
+ private operations;
573
+ constructor(factory: () => Promise<DrizzleQueryBuilder<T>>);
574
+ where(filter: FilterQuery<T>): this;
575
+ and(filter: FilterQuery<T>): this;
576
+ or(filters: FilterQuery<T>[]): this;
577
+ sort(sort: SortQuery<T>): this;
578
+ limit(count: number): this;
579
+ skip(count: number): this;
580
+ select(projection: ProjectionQuery<T>): this;
581
+ locale(loc: string): this;
582
+ version(versionId: string): this;
583
+ exec(): Promise<BaseSchema<T>[]>;
584
+ execOne(): Promise<BaseSchema<T> | null>;
585
+ count(): Promise<number>;
586
+ exists(): Promise<boolean>;
587
+ paginate(): Promise<PaginatedResult<BaseSchema<T>>>;
588
+ private buildChain;
589
+ }
590
+ declare class DrizzleQueryBuilder<T> extends QueryBuilder<T> {
591
+ private readonly db;
592
+ private readonly table;
593
+ private filterConditions;
594
+ private sortSpecs;
595
+ private selectedColumns;
596
+ private limitValue?;
597
+ private skipValue?;
598
+ private currentLocale?;
599
+ private currentVersion?;
600
+ constructor(db: DrizzleDB, table: PgTable, locale?: string, version?: string);
601
+ /**
602
+ * Add filter conditions to the query.
603
+ * Supports MongoDB-style operators like $gt, $lt, $in, $regex, etc.
604
+ */
605
+ where(filter: FilterQuery<T>): this;
606
+ /**
607
+ * Add additional AND conditions
608
+ */
609
+ and(filter: FilterQuery<T>): this;
610
+ /**
611
+ * Add OR conditions
612
+ */
613
+ or(filters: FilterQuery<T>[]): this;
614
+ /**
615
+ * Sort results by specified fields.
616
+ * Values can be 1 (asc), -1 (desc), 'asc', or 'desc'.
617
+ */
618
+ sort(sort: SortQuery<T>): this;
619
+ /**
620
+ * Limit the number of results
621
+ */
622
+ limit(count: number): this;
623
+ /**
624
+ * Skip a number of results (for pagination)
625
+ */
626
+ skip(count: number): this;
627
+ /**
628
+ * Select specific fields to return
629
+ */
630
+ select(projection: ProjectionQuery<T>): this;
631
+ /**
632
+ * Set the locale for query results
633
+ */
634
+ locale(locale: string): this;
635
+ /**
636
+ * Set the version filter for query
637
+ */
638
+ version(versionId: string): this;
639
+ /**
640
+ * Execute the query and return all matching documents
641
+ */
642
+ exec(): Promise<BaseSchema<T>[]>;
643
+ /**
644
+ * Execute the query and return a single document
645
+ */
646
+ execOne(): Promise<BaseSchema<T> | null>;
647
+ /**
648
+ * Count matching documents without fetching them
649
+ */
650
+ count(): Promise<number>;
651
+ /**
652
+ * Check if any matching documents exist
653
+ */
654
+ exists(): Promise<boolean>;
655
+ /**
656
+ * Execute with pagination info
657
+ */
658
+ paginate(): Promise<PaginatedResult<BaseSchema<T>>>;
659
+ /**
660
+ * Map MongoDB-style filter operators to Drizzle conditions.
661
+ * Note: Uses DynamicTableColumn for column references due to dynamic column access.
662
+ */
663
+ private mapFilter;
664
+ /**
665
+ * Map a single operator to a Drizzle condition.
666
+ * Note: Uses DynamicTableColumn for column parameter due to dynamic column access.
667
+ */
668
+ private mapOperator;
669
+ /**
670
+ * Map a database row to a result with camelCase keys
671
+ */
672
+ private mapResult;
673
+ }
674
+
675
+ /**
676
+ * Manages the migration history table (_magnet_migrations).
677
+ * Tracks which migrations have been applied, records checksums for validation.
678
+ */
679
+ declare class MigrationHistory {
680
+ private readonly db;
681
+ private readonly tableName;
682
+ constructor(db: MigrationDb, tableName: string);
683
+ /**
684
+ * Ensure the migrations history table exists.
685
+ */
686
+ ensureTable(): Promise<void>;
687
+ /**
688
+ * Get all applied migrations ordered by timestamp.
689
+ */
690
+ getApplied(): Promise<MigrationHistoryRecord[]>;
691
+ /**
692
+ * Record a newly applied migration.
693
+ */
694
+ recordMigration(record: MigrationHistoryRecord): Promise<void>;
695
+ /**
696
+ * Remove a migration record (for rollback).
697
+ */
698
+ removeMigration(id: string): Promise<void>;
699
+ /**
700
+ * Calculate a 16-char checksum (SHA-256 truncated) for a migration's up+down functions.
701
+ */
702
+ static calculateChecksum(up: (db: MigrationDb) => Promise<void>, down: (db: MigrationDb) => Promise<void>): string;
703
+ }
704
+
705
+ /**
706
+ * Manages the migration lock table to prevent concurrent migrations.
707
+ * Uses a simple INSERT-based locking with timeout for stale lock cleanup.
708
+ */
709
+ declare class MigrationLock {
710
+ private readonly db;
711
+ private readonly tableName;
712
+ private readonly lockTimeout;
713
+ constructor(db: MigrationDb, tableName: string, lockTimeout: number);
714
+ /**
715
+ * Ensure the lock table exists.
716
+ */
717
+ ensureTable(): Promise<void>;
718
+ /**
719
+ * Check if a valid (non-expired) lock exists.
720
+ */
721
+ isLocked(): Promise<boolean>;
722
+ /**
723
+ * Acquire the migration lock.
724
+ * Cleans up stale locks (older than lockTimeout) before attempting to lock.
725
+ * Throws MigrationLockError if another valid lock exists.
726
+ */
727
+ acquire(): Promise<void>;
728
+ /**
729
+ * Release the migration lock.
730
+ */
731
+ release(): Promise<void>;
732
+ }
733
+
734
+ /**
735
+ * Orchestrates migration execution: acquires lock, validates checksums,
736
+ * runs pending migrations in order, and releases lock on completion or error.
737
+ */
738
+ declare class MigrationRunner {
739
+ private readonly db;
740
+ private readonly config;
741
+ private readonly history;
742
+ private readonly lock;
743
+ constructor(db: MigrationDb, config: MigrationConfig);
744
+ /**
745
+ * Apply all pending migrations (or up to a specific migration ID).
746
+ */
747
+ up(migrations: Migration[], options?: {
748
+ to?: string;
749
+ }): Promise<MigrationResult>;
750
+ /**
751
+ * Roll back applied migrations. Without options, rolls back the last one.
752
+ * With options.to, rolls back all migrations after the target (exclusive).
753
+ */
754
+ down(migrations: Migration[], options?: {
755
+ to?: string;
756
+ }): Promise<void>;
757
+ /**
758
+ * Return the current migration status.
759
+ */
760
+ status(migrations: Migration[]): Promise<{
761
+ applied: MigrationHistoryRecord[];
762
+ pending: Migration[];
763
+ }>;
764
+ }
765
+
766
+ /**
767
+ * Default filename for persisted schema snapshot (used by auto-migration).
768
+ */
769
+ declare const SNAPSHOT_FILENAME = ".schema_snapshot.json";
770
+ /**
771
+ * A drizzle snapshot JSON (opaque to us — owned by drizzle-kit)
772
+ */
773
+ type SnapshotJSON = Record<string, unknown> & {
774
+ id: string;
775
+ prevId: string;
776
+ dialect: string;
777
+ };
778
+ /**
779
+ * Function signature for drizzle-kit's programmatic generateDrizzleJson / generateSQLiteDrizzleJson / generateMySQLDrizzleJson
780
+ */
781
+ type GenerateJsonFn = (imports: Record<string, unknown>, prevId?: string) => Promise<SnapshotJSON>;
782
+ /**
783
+ * Function signature for drizzle-kit's programmatic generateMigration / generateSQLiteMigration / generateMySQLMigration
784
+ */
785
+ type GenerateSQLFn = (prev: SnapshotJSON, cur: SnapshotJSON) => Promise<string[]>;
786
+ /**
787
+ * Bridges Magnet's decorator-generated Drizzle schemas to drizzle-kit's
788
+ * programmatic API for schema snapshotting and SQL diff generation.
789
+ */
790
+ declare class SchemaBridge {
791
+ /**
792
+ * Collect all registered schemas from the schema registry into a plain record
793
+ * suitable for passing to drizzle-kit's `generateDrizzleJson`.
794
+ */
795
+ collectSchemas(): Record<string, unknown>;
796
+ /**
797
+ * Generate a drizzle-kit snapshot for the current schemas.
798
+ *
799
+ * @param dialect - SQL dialect to use
800
+ * @param generateJsonFn - drizzle-kit's programmatic generateDrizzleJson function
801
+ * (injected for testability; defaults to importing from drizzle-kit/api at runtime)
802
+ */
803
+ generateSnapshot(dialect: MigrationDialect, generateJsonFn?: GenerateJsonFn): Promise<SnapshotJSON>;
804
+ /**
805
+ * Generate SQL statements to migrate from `prev` snapshot to `cur` snapshot.
806
+ *
807
+ * @param prev - Previous snapshot (empty for first migration)
808
+ * @param cur - Current snapshot
809
+ * @param generateSQLFn - drizzle-kit's programmatic generateMigration function
810
+ * (injected for testability; defaults to importing from drizzle-kit/api at runtime)
811
+ */
812
+ generateSQL(prev: SnapshotJSON, cur: SnapshotJSON, generateSQLFn?: GenerateSQLFn, dialect?: MigrationDialect): Promise<string[]>;
813
+ /**
814
+ * Load a previously saved snapshot from disk.
815
+ * Returns null if the file does not exist or is invalid.
816
+ */
817
+ loadSnapshot(directory: string): Promise<SnapshotJSON | null>;
818
+ /**
819
+ * Save a snapshot to disk for use as prevSnapshot on the next run.
820
+ */
821
+ saveSnapshot(directory: string, snapshot: SnapshotJSON): Promise<void>;
822
+ /**
823
+ * Generate an empty snapshot to use as the "previous" state for the first migration.
824
+ */
825
+ emptySnapshot(dialect: MigrationDialect): SnapshotJSON;
826
+ private resolveGenerateJsonFn;
827
+ private resolveGenerateSQLFn;
828
+ }
829
+
830
+ /**
831
+ * Result of a schema diff operation
832
+ */
833
+ interface SchemaDiffResult {
834
+ /** SQL statements for the up migration */
835
+ upSQL: string[];
836
+ /** Whether this diff contains dangerous operations */
837
+ dangerous: boolean;
838
+ /** Warning messages for dangerous operations */
839
+ warnings: string[];
840
+ /** Whether there are no changes */
841
+ isEmpty: boolean;
842
+ /** The current schema snapshot */
843
+ currentSnapshot: SnapshotJSON;
844
+ }
845
+ /**
846
+ * Diffs the current decorator schemas against a previous snapshot
847
+ * using drizzle-kit's programmatic API.
848
+ */
849
+ declare class SchemaDiff {
850
+ private readonly bridge;
851
+ constructor(bridge: SchemaBridge);
852
+ /**
853
+ * Generate a diff between the previous snapshot and the current schema state.
854
+ *
855
+ * @param dialect - SQL dialect to use
856
+ * @param prevSnapshot - Previous snapshot (uses empty snapshot if not provided)
857
+ */
858
+ diff(dialect: MigrationDialect, prevSnapshot?: SnapshotJSON): Promise<SchemaDiffResult>;
859
+ /**
860
+ * Scan SQL statements for dangerous operations (drops, type changes).
861
+ */
862
+ detectDangerousOperations(sqlStatements: string[]): {
863
+ dangerous: boolean;
864
+ warnings: string[];
865
+ };
866
+ }
867
+
868
+ interface MigrationGenerateOptions {
869
+ dangerous?: boolean;
870
+ warnings?: string[];
871
+ }
872
+ /**
873
+ * Generates TypeScript migration files from SQL statements.
874
+ */
875
+ declare class MigrationGenerator {
876
+ /**
877
+ * Generate the TypeScript content of a migration file.
878
+ */
879
+ generate(name: string, upSQL: string[], downSQL: string[], options?: MigrationGenerateOptions): string;
880
+ /**
881
+ * Determine the next sequential migration number for a directory.
882
+ * Returns 1 if the directory is empty, otherwise the highest number + 1.
883
+ */
884
+ nextMigrationNumber(directory: string): Promise<number>;
885
+ /**
886
+ * Write a migration file to the directory with sequential numbering.
887
+ */
888
+ writeMigrationFile(directory: string, name: string, content: string): Promise<{
889
+ filename: string;
890
+ path: string;
891
+ }>;
892
+ }
893
+
894
+ /**
895
+ * PostgreSQL-specific SQL generation helpers.
896
+ * Primary SQL generation is handled by drizzle-kit's generateMigration/generateDrizzleJson.
897
+ * These helpers are for manual SQL generation when needed.
898
+ */
899
+ interface ColumnDef {
900
+ name: string;
901
+ type: string;
902
+ nullable?: boolean;
903
+ default?: string;
904
+ primaryKey?: boolean;
905
+ }
906
+ interface IndexDef {
907
+ name: string;
908
+ table: string;
909
+ columns: string[];
910
+ unique?: boolean;
911
+ }
912
+ /**
913
+ * Generate CREATE TABLE SQL for PostgreSQL
914
+ */
915
+ declare function createTable$2(tableName: string, columns: ColumnDef[]): string;
916
+ /**
917
+ * Generate DROP TABLE SQL for PostgreSQL
918
+ */
919
+ declare function dropTable$2(tableName: string): string;
920
+ /**
921
+ * Generate ADD COLUMN SQL for PostgreSQL
922
+ */
923
+ declare function addColumn$2(tableName: string, column: ColumnDef): string;
924
+ /**
925
+ * Generate DROP COLUMN SQL for PostgreSQL
926
+ */
927
+ declare function dropColumn$1(tableName: string, columnName: string): string;
928
+ /**
929
+ * Generate ALTER COLUMN TYPE SQL for PostgreSQL
930
+ */
931
+ declare function alterColumnType(tableName: string, columnName: string, newType: string): string;
932
+ /**
933
+ * Generate CREATE INDEX SQL for PostgreSQL
934
+ */
935
+ declare function createIndex$2(idx: IndexDef): string;
936
+ /**
937
+ * Generate DROP INDEX SQL for PostgreSQL
938
+ */
939
+ declare function dropIndex$2(indexName: string): string;
940
+
941
+ type postgresql_ColumnDef = ColumnDef;
942
+ type postgresql_IndexDef = IndexDef;
943
+ declare const postgresql_alterColumnType: typeof alterColumnType;
944
+ declare namespace postgresql {
945
+ export { type postgresql_ColumnDef as ColumnDef, type postgresql_IndexDef as IndexDef, addColumn$2 as addColumn, postgresql_alterColumnType as alterColumnType, createIndex$2 as createIndex, createTable$2 as createTable, dropColumn$1 as dropColumn, dropIndex$2 as dropIndex, dropTable$2 as dropTable };
946
+ }
947
+
948
+ /**
949
+ * MySQL-specific SQL generation helpers.
950
+ * Primary SQL generation is handled by drizzle-kit's generateMySQLMigration/generateMySQLDrizzleJson.
951
+ */
952
+
953
+ /**
954
+ * Generate CREATE TABLE SQL for MySQL
955
+ */
956
+ declare function createTable$1(tableName: string, columns: ColumnDef[]): string;
957
+ /**
958
+ * Generate DROP TABLE SQL for MySQL
959
+ */
960
+ declare function dropTable$1(tableName: string): string;
961
+ /**
962
+ * Generate ADD COLUMN SQL for MySQL
963
+ */
964
+ declare function addColumn$1(tableName: string, column: ColumnDef): string;
965
+ /**
966
+ * Generate DROP COLUMN SQL for MySQL
967
+ */
968
+ declare function dropColumn(tableName: string, columnName: string): string;
969
+ /**
970
+ * Generate MODIFY COLUMN SQL for MySQL (used for type changes)
971
+ */
972
+ declare function modifyColumn(tableName: string, column: ColumnDef): string;
973
+ /**
974
+ * Generate CREATE INDEX SQL for MySQL
975
+ */
976
+ declare function createIndex$1(idx: IndexDef): string;
977
+ /**
978
+ * Generate DROP INDEX SQL for MySQL
979
+ */
980
+ declare function dropIndex$1(indexName: string, tableName: string): string;
981
+
982
+ type mysql_ColumnDef = ColumnDef;
983
+ type mysql_IndexDef = IndexDef;
984
+ declare const mysql_dropColumn: typeof dropColumn;
985
+ declare const mysql_modifyColumn: typeof modifyColumn;
986
+ declare namespace mysql {
987
+ export { type mysql_ColumnDef as ColumnDef, type mysql_IndexDef as IndexDef, addColumn$1 as addColumn, createIndex$1 as createIndex, createTable$1 as createTable, mysql_dropColumn as dropColumn, dropIndex$1 as dropIndex, dropTable$1 as dropTable, mysql_modifyColumn as modifyColumn };
988
+ }
989
+
990
+ /**
991
+ * SQLite-specific SQL generation helpers.
992
+ * Primary SQL generation is handled by drizzle-kit's generateSQLiteMigration/generateSQLiteDrizzleJson.
993
+ *
994
+ * Note: SQLite has limited ALTER TABLE support — no DROP COLUMN or MODIFY COLUMN.
995
+ * Complex schema changes require table recreation (rename old, create new, copy data, drop old).
996
+ */
997
+
998
+ /**
999
+ * Generate CREATE TABLE SQL for SQLite
1000
+ */
1001
+ declare function createTable(tableName: string, columns: ColumnDef[]): string;
1002
+ /**
1003
+ * Generate DROP TABLE SQL for SQLite
1004
+ */
1005
+ declare function dropTable(tableName: string): string;
1006
+ /**
1007
+ * Generate ADD COLUMN SQL for SQLite
1008
+ * Note: SQLite ADD COLUMN is limited — no NOT NULL without DEFAULT, no UNIQUE, no PRIMARY KEY
1009
+ */
1010
+ declare function addColumn(tableName: string, column: ColumnDef): string;
1011
+ /**
1012
+ * Generate CREATE INDEX SQL for SQLite
1013
+ */
1014
+ declare function createIndex(idx: IndexDef): string;
1015
+ /**
1016
+ * Generate DROP INDEX SQL for SQLite
1017
+ */
1018
+ declare function dropIndex(indexName: string): string;
1019
+
1020
+ type sqlite_ColumnDef = ColumnDef;
1021
+ type sqlite_IndexDef = IndexDef;
1022
+ declare const sqlite_addColumn: typeof addColumn;
1023
+ declare const sqlite_createIndex: typeof createIndex;
1024
+ declare const sqlite_createTable: typeof createTable;
1025
+ declare const sqlite_dropIndex: typeof dropIndex;
1026
+ declare const sqlite_dropTable: typeof dropTable;
1027
+ declare namespace sqlite {
1028
+ export { type sqlite_ColumnDef as ColumnDef, type sqlite_IndexDef as IndexDef, sqlite_addColumn as addColumn, sqlite_createIndex as createIndex, sqlite_createTable as createTable, sqlite_dropIndex as dropIndex, sqlite_dropTable as dropTable };
1029
+ }
1030
+
1031
+ type index_ColumnDef = ColumnDef;
1032
+ type index_IndexDef = IndexDef;
1033
+ declare const index_mysql: typeof mysql;
1034
+ declare const index_postgresql: typeof postgresql;
1035
+ declare const index_sqlite: typeof sqlite;
1036
+ declare namespace index {
1037
+ export { type index_ColumnDef as ColumnDef, type index_IndexDef as IndexDef, index_mysql as mysql, index_postgresql as postgresql, index_sqlite as sqlite };
1038
+ }
1039
+
1040
+ /**
1041
+ * Handles automatic migration detection and application on adapter startup.
1042
+ *
1043
+ * In `auto` mode: detects diff → generates migration file → applies it.
1044
+ * In `manual` mode: detects diff → logs warning only (does not apply).
1045
+ * No `migrations` config: caller falls back to legacy CREATE TABLE IF NOT EXISTS.
1046
+ */
1047
+ declare class AutoMigration {
1048
+ private readonly bridge;
1049
+ private readonly diff;
1050
+ private readonly gen;
1051
+ private readonly runner;
1052
+ constructor(bridge: SchemaBridge, diff: SchemaDiff, gen: MigrationGenerator, runner: MigrationRunner);
1053
+ /**
1054
+ * Check for schema changes and handle them based on the migration mode.
1055
+ */
1056
+ run(dialect: MigrationDialect, config: MigrationConfig, directory: string): Promise<void>;
1057
+ }
1058
+
1059
+ export { Adapter, AutoMigration, type ColumnChange, DEFAULT_LOCALE, DEFAULT_MIGRATION_CONFIG, DOCUMENT_STATUS, DRIZZLE_CONFIG, DRIZZLE_DB, type DiffResult, type DocumentColumnOptions, type DocumentStatus, type DrizzleConfig, type DrizzleDB, DrizzleDatabaseAdapter, type DrizzleModuleOptions, DrizzleQueryBuilder, type GenerateJsonFn, type GenerateSQLFn, type GeneratedSchema, type IndexChange, InjectModel, LazyQueryBuilder, type Migration, MigrationChecksumError, type MigrationConfig, type MigrationDb, type MigrationDialect, MigrationError, type MigrationGenerateOptions, MigrationGenerator, MigrationHistory, type MigrationHistoryRecord, MigrationLock, MigrationLockError, type MigrationMode, type MigrationResult, MigrationRunner, Prop, type PropMetadata, SNAPSHOT_FILENAME, Schema, SchemaBridge, SchemaDiff, type SchemaDiffResult, type SchemaMetadata, type SnapshotJSON, type TableDefinition, applyDocumentColumns, clearSchemaRegistry, createNeonConnection, createNeonWebSocketConnection, generateSchema, getDrizzleModelToken, getDrizzlePropsMetadata, getDrizzleSchemaMetadata, getOrGenerateSchema, getRegisteredSchemas, isDraft, isPublished, index as sqlGenerators };