@nextlyhq/adapter-drizzle 0.0.1

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.
Files changed (43) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +9 -0
  3. package/dist/adapter-BxJVtttb.d.ts +592 -0
  4. package/dist/adapter-nvlxFkF-.d.cts +592 -0
  5. package/dist/core-CVO7WYDj.d.cts +74 -0
  6. package/dist/core-CVO7WYDj.d.ts +74 -0
  7. package/dist/error-um1d_3Uo.d.cts +105 -0
  8. package/dist/error-um1d_3Uo.d.ts +105 -0
  9. package/dist/index.cjs +1137 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.cts +57 -0
  12. package/dist/index.d.ts +57 -0
  13. package/dist/index.mjs +1134 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/dist/migration-BbO5meEV.d.cts +622 -0
  16. package/dist/migration-Qe70wDOC.d.ts +622 -0
  17. package/dist/migrations.cjs +195 -0
  18. package/dist/migrations.cjs.map +1 -0
  19. package/dist/migrations.d.cts +351 -0
  20. package/dist/migrations.d.ts +351 -0
  21. package/dist/migrations.mjs +185 -0
  22. package/dist/migrations.mjs.map +1 -0
  23. package/dist/schema/index.cjs +10 -0
  24. package/dist/schema/index.cjs.map +1 -0
  25. package/dist/schema/index.d.cts +133 -0
  26. package/dist/schema/index.d.ts +133 -0
  27. package/dist/schema/index.mjs +7 -0
  28. package/dist/schema/index.mjs.map +1 -0
  29. package/dist/schema-BDn8WfSL.d.cts +200 -0
  30. package/dist/schema-BIQ0YQZ_.d.ts +200 -0
  31. package/dist/types/index.cjs +24 -0
  32. package/dist/types/index.cjs.map +1 -0
  33. package/dist/types/index.d.cts +210 -0
  34. package/dist/types/index.d.ts +210 -0
  35. package/dist/types/index.mjs +21 -0
  36. package/dist/types/index.mjs.map +1 -0
  37. package/dist/version-check.cjs +154 -0
  38. package/dist/version-check.cjs.map +1 -0
  39. package/dist/version-check.d.cts +43 -0
  40. package/dist/version-check.d.ts +43 -0
  41. package/dist/version-check.mjs +150 -0
  42. package/dist/version-check.mjs.map +1 -0
  43. package/package.json +94 -0
@@ -0,0 +1,195 @@
1
+ 'use strict';
2
+
3
+ var crypto = require('crypto');
4
+
5
+ // src/migrations.ts
6
+ function calculateChecksum(migration) {
7
+ const content = JSON.stringify({
8
+ id: migration.id,
9
+ name: migration.name,
10
+ timestamp: migration.timestamp,
11
+ up: typeof migration.up === "string" ? migration.up : migration.up.toString(),
12
+ down: typeof migration.down === "string" ? migration.down : migration.down?.toString() || null
13
+ });
14
+ return crypto.createHash("sha256").update(content, "utf8").digest("hex");
15
+ }
16
+ function sortMigrations(migrations) {
17
+ return [...migrations].sort((a, b) => {
18
+ if (a.timestamp !== b.timestamp) {
19
+ return a.timestamp - b.timestamp;
20
+ }
21
+ return a.id.localeCompare(b.id);
22
+ });
23
+ }
24
+ function filterPending(migrations, applied) {
25
+ const appliedIds = new Set(applied.map((record) => record.id));
26
+ return migrations.filter((migration) => !appliedIds.has(migration.id));
27
+ }
28
+ function filterApplied(migrations, applied) {
29
+ const migrationIds = new Set(migrations.map((migration) => migration.id));
30
+ return applied.filter((record) => migrationIds.has(record.id));
31
+ }
32
+ function validateChecksum(migration, record) {
33
+ if (!record.checksum) {
34
+ return false;
35
+ }
36
+ const currentChecksum = calculateChecksum(migration);
37
+ return currentChecksum === record.checksum;
38
+ }
39
+ function detectModified(migrations, applied) {
40
+ const migrationMap = new Map(migrations.map((m) => [m.id, m]));
41
+ const modified = [];
42
+ for (const record of applied) {
43
+ const migration = migrationMap.get(record.id);
44
+ if (migration && !validateChecksum(migration, record)) {
45
+ modified.push(record);
46
+ }
47
+ }
48
+ return modified;
49
+ }
50
+ function getMigrationStatus(migrations, applied) {
51
+ const sortedMigrations = sortMigrations(migrations);
52
+ const sortedApplied = [...applied].sort(
53
+ (a, b) => b.appliedAt.getTime() - a.appliedAt.getTime()
54
+ );
55
+ const pending = filterPending(sortedMigrations, applied);
56
+ const current = sortedApplied.length > 0 ? sortedApplied[0].id : null;
57
+ return {
58
+ current,
59
+ appliedCount: applied.length,
60
+ pendingCount: pending.length,
61
+ applied,
62
+ pending
63
+ };
64
+ }
65
+ function validateMigrations(migrations, applied, options) {
66
+ const errors = [];
67
+ const warnings = [];
68
+ const duplicates = [];
69
+ const idCounts = /* @__PURE__ */ new Map();
70
+ for (const migration of migrations) {
71
+ const count = (idCounts.get(migration.id) || 0) + 1;
72
+ idCounts.set(migration.id, count);
73
+ if (count > 1) {
74
+ duplicates.push(migration.id);
75
+ }
76
+ }
77
+ if (duplicates.length > 0) {
78
+ errors.push(`Duplicate migration IDs found: ${duplicates.join(", ")}`);
79
+ }
80
+ for (const migration of migrations) {
81
+ if (!migration.id) {
82
+ errors.push("Migration missing required field: id");
83
+ }
84
+ if (!migration.name) {
85
+ errors.push(`Migration ${migration.id} missing required field: name`);
86
+ }
87
+ if (!migration.timestamp || typeof migration.timestamp !== "number") {
88
+ errors.push(`Migration ${migration.id} missing or invalid timestamp`);
89
+ }
90
+ if (!migration.up) {
91
+ errors.push(`Migration ${migration.id} missing required field: up`);
92
+ }
93
+ }
94
+ const modified = detectModified(migrations, applied);
95
+ if (modified.length > 0) {
96
+ const modifiedIds = modified.map((r) => r.id).join(", ");
97
+ const message = `Applied migrations have been modified: ${modifiedIds}`;
98
+ const strictChecksums = options?.strictChecksums ?? true;
99
+ if (strictChecksums) {
100
+ errors.push(message);
101
+ } else {
102
+ warnings.push(message);
103
+ }
104
+ }
105
+ return {
106
+ valid: errors.length === 0,
107
+ errors,
108
+ warnings,
109
+ modified,
110
+ duplicates
111
+ };
112
+ }
113
+ var migrationHelpers = {
114
+ async createMigrationsTable(adapter) {
115
+ const caps = adapter.getCapabilities();
116
+ const dialect = caps.dialect;
117
+ let sql = "";
118
+ if (dialect === "postgresql") {
119
+ sql = `
120
+ CREATE TABLE IF NOT EXISTS nextly_migrations (
121
+ id VARCHAR(255) PRIMARY KEY,
122
+ name VARCHAR(255) NOT NULL,
123
+ applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
124
+ checksum VARCHAR(64)
125
+ )
126
+ `;
127
+ } else if (dialect === "mysql") {
128
+ sql = `
129
+ CREATE TABLE IF NOT EXISTS nextly_migrations (
130
+ id VARCHAR(255) PRIMARY KEY,
131
+ name VARCHAR(255) NOT NULL,
132
+ applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
133
+ checksum VARCHAR(64)
134
+ )
135
+ `;
136
+ } else if (dialect === "sqlite") {
137
+ sql = `
138
+ CREATE TABLE IF NOT EXISTS nextly_migrations (
139
+ id TEXT PRIMARY KEY,
140
+ name TEXT NOT NULL,
141
+ applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
142
+ checksum TEXT
143
+ )
144
+ `;
145
+ } else {
146
+ throw new Error(`Unsupported dialect: ${String(dialect)}`);
147
+ }
148
+ await adapter.executeQuery(sql);
149
+ },
150
+ async getAppliedMigrations(adapter) {
151
+ const results = await adapter.select("nextly_migrations", {
152
+ orderBy: [{ column: "applied_at", direction: "desc" }]
153
+ });
154
+ return results.map((row) => ({
155
+ id: row.id,
156
+ name: row.name,
157
+ appliedAt: new Date(row.applied_at),
158
+ checksum: row.checksum
159
+ }));
160
+ },
161
+ async recordMigration(adapter, migration) {
162
+ const checksum = calculateChecksum(migration);
163
+ await adapter.insert("nextly_migrations", {
164
+ id: migration.id,
165
+ name: migration.name,
166
+ applied_at: /* @__PURE__ */ new Date(),
167
+ checksum
168
+ });
169
+ },
170
+ async removeMigrationRecord(adapter, migrationId) {
171
+ await adapter.delete("nextly_migrations", {
172
+ and: [{ column: "id", op: "=", value: migrationId }]
173
+ });
174
+ },
175
+ async migrationsTableExists(adapter) {
176
+ try {
177
+ await adapter.select("nextly_migrations", { limit: 1 });
178
+ return true;
179
+ } catch {
180
+ return false;
181
+ }
182
+ }
183
+ };
184
+
185
+ exports.calculateChecksum = calculateChecksum;
186
+ exports.detectModified = detectModified;
187
+ exports.filterApplied = filterApplied;
188
+ exports.filterPending = filterPending;
189
+ exports.getMigrationStatus = getMigrationStatus;
190
+ exports.migrationHelpers = migrationHelpers;
191
+ exports.sortMigrations = sortMigrations;
192
+ exports.validateChecksum = validateChecksum;
193
+ exports.validateMigrations = validateMigrations;
194
+ //# sourceMappingURL=migrations.cjs.map
195
+ //# sourceMappingURL=migrations.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/migrations.ts"],"names":["createHash"],"mappings":"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","file":"migrations.cjs","sourcesContent":["/**\n * Database migration utilities.\n *\n * @remarks\n * Provides core utilities for migration management including checksum calculation,\n * sorting, filtering, and validation. Also includes optional helpers for adapters\n * to use for common migration operations.\n *\n * @packageDocumentation\n */\n\nimport { createHash } from \"crypto\";\n\nimport type { DrizzleAdapter } from \"./adapter\";\nimport type {\n Migration,\n MigrationRecord,\n MigrationStatus,\n MigrationOptions,\n} from \"./types/migration\";\n\n// ============================================================\n// Core Utilities\n// ============================================================\n\n/**\n * Calculate SHA-256 checksum for a migration.\n *\n * @remarks\n * Creates a checksum of the entire migration object including id, name, timestamp,\n * and the string representation of up/down functions. This allows detection of\n * any changes to the migration after it has been applied.\n *\n * @param migration - Migration to calculate checksum for\n * @returns Hexadecimal SHA-256 hash\n *\n * @example\n * ```typescript\n * const migration: Migration = {\n * id: \"20250104_001_create_users\",\n * name: \"Create users table\",\n * timestamp: 1704326400000,\n * up: \"CREATE TABLE users (id UUID PRIMARY KEY);\",\n * };\n *\n * const checksum = calculateChecksum(migration);\n * // Returns: \"a3f5b8c9d2e1f0...\"\n * ```\n *\n * @public\n */\nexport function calculateChecksum(migration: Migration): string {\n // Serialize migration to a consistent string format\n const content = JSON.stringify({\n id: migration.id,\n name: migration.name,\n timestamp: migration.timestamp,\n up:\n typeof migration.up === \"string\" ? migration.up : migration.up.toString(),\n down:\n typeof migration.down === \"string\"\n ? migration.down\n : migration.down?.toString() || null,\n });\n\n // Create SHA-256 hash\n return createHash(\"sha256\").update(content, \"utf8\").digest(\"hex\");\n}\n\n/**\n * Sort migrations by timestamp in ascending order.\n *\n * @remarks\n * Provides deterministic ordering of migrations. If timestamps are equal,\n * falls back to sorting by migration ID alphabetically.\n *\n * @param migrations - Array of migrations to sort\n * @returns New sorted array (original array is not modified)\n *\n * @example\n * ```typescript\n * const migrations = [\n * { id: \"003\", timestamp: 1704412800000, ... },\n * { id: \"001\", timestamp: 1704326400000, ... },\n * { id: \"002\", timestamp: 1704326400000, ... },\n * ];\n *\n * const sorted = sortMigrations(migrations);\n * // Returns: [001, 002, 003] (001 and 002 same timestamp, sorted by id)\n * ```\n *\n * @public\n */\nexport function sortMigrations(migrations: Migration[]): Migration[] {\n return [...migrations].sort((a, b) => {\n // Primary sort: timestamp ascending\n if (a.timestamp !== b.timestamp) {\n return a.timestamp - b.timestamp;\n }\n // Secondary sort: id alphabetically (for deterministic ordering)\n return a.id.localeCompare(b.id);\n });\n}\n\n/**\n * Filter migrations to get only pending (unapplied) migrations.\n *\n * @remarks\n * Returns migrations that have not been applied to the database yet.\n * A migration is considered pending if its ID is not present in the\n * applied migration records.\n *\n * @param migrations - All available migrations\n * @param applied - Records of applied migrations from database\n * @returns Array of pending migrations\n *\n * @example\n * ```typescript\n * const allMigrations = [\n * { id: \"001_create_users\", ... },\n * { id: \"002_create_posts\", ... },\n * { id: \"003_create_comments\", ... },\n * ];\n *\n * const appliedRecords = [\n * { id: \"001_create_users\", appliedAt: new Date(), ... },\n * ];\n *\n * const pending = filterPending(allMigrations, appliedRecords);\n * // Returns: [002_create_posts, 003_create_comments]\n * ```\n *\n * @public\n */\nexport function filterPending(\n migrations: Migration[],\n applied: MigrationRecord[]\n): Migration[] {\n const appliedIds = new Set(applied.map(record => record.id));\n return migrations.filter(migration => !appliedIds.has(migration.id));\n}\n\n/**\n * Filter migration records to get only those that match given migrations.\n *\n * @remarks\n * Returns applied migration records that correspond to the given migrations.\n * Useful for getting the subset of applied records relevant to a specific\n * set of migrations.\n *\n * @param migrations - Migrations to match\n * @param applied - All applied migration records from database\n * @returns Array of matching applied records\n *\n * @example\n * ```typescript\n * const migrations = [\n * { id: \"001_create_users\", ... },\n * { id: \"002_create_posts\", ... },\n * ];\n *\n * const allApplied = [\n * { id: \"001_create_users\", appliedAt: new Date(), ... },\n * { id: \"002_create_posts\", appliedAt: new Date(), ... },\n * { id: \"003_create_comments\", appliedAt: new Date(), ... },\n * ];\n *\n * const relevant = filterApplied(migrations, allApplied);\n * // Returns: [001_create_users, 002_create_posts]\n * ```\n *\n * @public\n */\nexport function filterApplied(\n migrations: Migration[],\n applied: MigrationRecord[]\n): MigrationRecord[] {\n const migrationIds = new Set(migrations.map(migration => migration.id));\n return applied.filter(record => migrationIds.has(record.id));\n}\n\n/**\n * Validate that a migration's checksum matches its applied record.\n *\n * @remarks\n * Compares the calculated checksum of a migration against the stored checksum\n * in its migration record. Returns false if checksums don't match or if the\n * record has no checksum.\n *\n * @param migration - Migration to validate\n * @param record - Applied migration record with stored checksum\n * @returns true if checksums match, false otherwise\n *\n * @example\n * ```typescript\n * const migration: Migration = { id: \"001\", ... };\n * const record: MigrationRecord = {\n * id: \"001\",\n * checksum: \"a3f5b8c9...\",\n * ...\n * };\n *\n * const isValid = validateChecksum(migration, record);\n * // Returns: true if checksums match, false if modified\n * ```\n *\n * @public\n */\nexport function validateChecksum(\n migration: Migration,\n record: MigrationRecord\n): boolean {\n if (!record.checksum) {\n // No checksum stored, cannot validate\n return false;\n }\n\n const currentChecksum = calculateChecksum(migration);\n return currentChecksum === record.checksum;\n}\n\n/**\n * Detect migrations that have been modified after being applied.\n *\n * @remarks\n * Compares checksums of migrations against their applied records to detect\n * any modifications. Returns records for migrations that have been changed\n * since they were applied to the database.\n *\n * This is critical for detecting potentially dangerous situations where a\n * migration that has already run has been modified.\n *\n * @param migrations - Current migrations\n * @param applied - Applied migration records with checksums\n * @returns Array of records for modified migrations\n *\n * @example\n * ```typescript\n * const migrations = [{ id: \"001\", up: \"CREATE TABLE users_v2 ...\" }];\n * const applied = [{ id: \"001\", checksum: \"original_hash\", ... }];\n *\n * const modified = detectModified(migrations, applied);\n * // Returns: [{ id: \"001\", ... }] if migration was changed\n * ```\n *\n * @public\n */\nexport function detectModified(\n migrations: Migration[],\n applied: MigrationRecord[]\n): MigrationRecord[] {\n const migrationMap = new Map(migrations.map(m => [m.id, m]));\n const modified: MigrationRecord[] = [];\n\n for (const record of applied) {\n const migration = migrationMap.get(record.id);\n if (migration && !validateChecksum(migration, record)) {\n modified.push(record);\n }\n }\n\n return modified;\n}\n\n/**\n * Get comprehensive migration status.\n *\n * @remarks\n * Analyzes migrations and applied records to produce a complete status report\n * including current migration, applied/pending counts, and full lists.\n *\n * @param migrations - All available migrations\n * @param applied - Applied migration records from database\n * @returns Complete migration status information\n *\n * @example\n * ```typescript\n * const status = getMigrationStatus(allMigrations, appliedRecords);\n * console.log(`Current: ${status.current}`);\n * console.log(`Applied: ${status.appliedCount}, Pending: ${status.pendingCount}`);\n * ```\n *\n * @public\n */\nexport function getMigrationStatus(\n migrations: Migration[],\n applied: MigrationRecord[]\n): MigrationStatus {\n const sortedMigrations = sortMigrations(migrations);\n const sortedApplied = [...applied].sort(\n (a, b) => b.appliedAt.getTime() - a.appliedAt.getTime()\n );\n\n const pending = filterPending(sortedMigrations, applied);\n const current = sortedApplied.length > 0 ? sortedApplied[0].id : null;\n\n return {\n current,\n appliedCount: applied.length,\n pendingCount: pending.length,\n applied,\n pending,\n };\n}\n\n// ============================================================\n// Migration Validation\n// ============================================================\n\n/**\n * Validation result for migrations.\n *\n * @public\n */\nexport interface MigrationValidationResult {\n /** Whether all validations passed */\n valid: boolean;\n\n /** List of validation errors */\n errors: string[];\n\n /** List of validation warnings */\n warnings: string[];\n\n /** Migrations that have been modified */\n modified: MigrationRecord[];\n\n /** Duplicate migration IDs found */\n duplicates: string[];\n}\n\n/**\n * Validate migrations for common issues.\n *\n * @remarks\n * Performs comprehensive validation including:\n * - Duplicate migration IDs\n * - Modified applied migrations (checksum mismatch)\n * - Missing required fields\n * - Invalid timestamps\n *\n * @param migrations - Migrations to validate\n * @param applied - Applied migration records (for checksum validation)\n * @param options - Migration options (for strictness configuration)\n * @returns Validation result with errors and warnings\n *\n * @example\n * ```typescript\n * const result = validateMigrations(migrations, applied, {\n * strictChecksums: true\n * });\n *\n * if (!result.valid) {\n * console.error(\"Validation errors:\", result.errors);\n * throw new Error(\"Migration validation failed\");\n * }\n * ```\n *\n * @public\n */\nexport function validateMigrations(\n migrations: Migration[],\n applied: MigrationRecord[],\n options?: MigrationOptions\n): MigrationValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n const duplicates: string[] = [];\n\n // Check for duplicate IDs\n const idCounts = new Map<string, number>();\n for (const migration of migrations) {\n const count = (idCounts.get(migration.id) || 0) + 1;\n idCounts.set(migration.id, count);\n if (count > 1) {\n duplicates.push(migration.id);\n }\n }\n\n if (duplicates.length > 0) {\n errors.push(`Duplicate migration IDs found: ${duplicates.join(\", \")}`);\n }\n\n // Validate required fields\n for (const migration of migrations) {\n if (!migration.id) {\n errors.push(\"Migration missing required field: id\");\n }\n if (!migration.name) {\n errors.push(`Migration ${migration.id} missing required field: name`);\n }\n if (!migration.timestamp || typeof migration.timestamp !== \"number\") {\n errors.push(`Migration ${migration.id} missing or invalid timestamp`);\n }\n if (!migration.up) {\n errors.push(`Migration ${migration.id} missing required field: up`);\n }\n }\n\n // Check for modified migrations\n const modified = detectModified(migrations, applied);\n\n if (modified.length > 0) {\n const modifiedIds = modified.map(r => r.id).join(\", \");\n const message = `Applied migrations have been modified: ${modifiedIds}`;\n\n // Use strictChecksums option if available, default to true (strict)\n const strictChecksums = options?.strictChecksums ?? true;\n\n if (strictChecksums) {\n errors.push(message);\n } else {\n warnings.push(message);\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n modified,\n duplicates,\n };\n}\n\n// ============================================================\n// Migration Helpers (for adapters)\n// ============================================================\n\n/**\n * Helper functions for managing migrations in database adapters.\n *\n * @remarks\n * These helpers reduce boilerplate code in dialect-specific adapters by\n * providing common operations like creating migration tables, recording\n * migrations, and querying migration status.\n *\n * Adapters can use these helpers or implement their own logic.\n *\n * @public\n */\nexport interface MigrationHelpers {\n /**\n * Create the migrations tracking table if it doesn't exist.\n *\n * @remarks\n * Creates a table named `nextly_migrations` with columns:\n * - id (string, primary key)\n * - name (string)\n * - applied_at (timestamp)\n * - checksum (string, optional)\n *\n * Uses CREATE TABLE IF NOT EXISTS for safety.\n *\n * @param adapter - Database adapter to use\n * @returns Promise that resolves when table is created\n */\n createMigrationsTable(adapter: DrizzleAdapter): Promise<void>;\n\n /**\n * Get all applied migration records from the database.\n *\n * @remarks\n * Queries the `nextly_migrations` table and returns all records\n * sorted by applied_at descending (most recent first).\n *\n * @param adapter - Database adapter to use\n * @returns Promise with array of applied migration records\n */\n getAppliedMigrations(adapter: DrizzleAdapter): Promise<MigrationRecord[]>;\n\n /**\n * Record a migration as applied in the database.\n *\n * @remarks\n * Inserts a new record into the `nextly_migrations` table with:\n * - Migration ID, name\n * - Current timestamp for applied_at\n * - Calculated checksum\n *\n * Should be called within a transaction during migration execution.\n *\n * @param adapter - Database adapter to use\n * @param migration - Migration that was applied\n * @returns Promise that resolves when record is inserted\n */\n recordMigration(adapter: DrizzleAdapter, migration: Migration): Promise<void>;\n\n /**\n * Remove a migration record from the database.\n *\n * @remarks\n * Deletes a record from the `nextly_migrations` table.\n * Used during migration rollback operations.\n *\n * Should be called within a transaction during rollback.\n *\n * @param adapter - Database adapter to use\n * @param migrationId - ID of the migration to remove\n * @returns Promise that resolves when record is deleted\n */\n removeMigrationRecord(\n adapter: DrizzleAdapter,\n migrationId: string\n ): Promise<void>;\n\n /**\n * Check if migrations table exists.\n *\n * @remarks\n * Queries database metadata to check if the `nextly_migrations` table exists.\n * Useful for determining if initialization is needed.\n *\n * @param adapter - Database adapter to use\n * @returns Promise with boolean indicating if table exists\n */\n migrationsTableExists(adapter: DrizzleAdapter): Promise<boolean>;\n}\n\n/**\n * Implementation of migration helpers.\n *\n * @remarks\n * Provides default implementations using the adapter's query methods.\n * These work across all dialects but adapters can optimize for their\n * specific database if needed.\n *\n * @public\n */\nexport const migrationHelpers: MigrationHelpers = {\n async createMigrationsTable(adapter: DrizzleAdapter): Promise<void> {\n const caps = adapter.getCapabilities();\n const dialect = caps.dialect;\n\n // Build CREATE TABLE statement with dialect-specific syntax\n let sql = \"\";\n\n if (dialect === \"postgresql\") {\n sql = `\n CREATE TABLE IF NOT EXISTS nextly_migrations (\n id VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n checksum VARCHAR(64)\n )\n `;\n } else if (dialect === \"mysql\") {\n sql = `\n CREATE TABLE IF NOT EXISTS nextly_migrations (\n id VARCHAR(255) PRIMARY KEY,\n name VARCHAR(255) NOT NULL,\n applied_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n checksum VARCHAR(64)\n )\n `;\n } else if (dialect === \"sqlite\") {\n sql = `\n CREATE TABLE IF NOT EXISTS nextly_migrations (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n checksum TEXT\n )\n `;\n } else {\n throw new Error(`Unsupported dialect: ${String(dialect)}`);\n }\n\n await adapter.executeQuery(sql);\n },\n\n async getAppliedMigrations(\n adapter: DrizzleAdapter\n ): Promise<MigrationRecord[]> {\n const results = await adapter.select<{\n id: string;\n name: string;\n applied_at: Date;\n checksum?: string;\n }>(\"nextly_migrations\", {\n orderBy: [{ column: \"applied_at\", direction: \"desc\" }],\n });\n\n return results.map(row => ({\n id: row.id,\n name: row.name,\n appliedAt: new Date(row.applied_at),\n checksum: row.checksum,\n }));\n },\n\n async recordMigration(\n adapter: DrizzleAdapter,\n migration: Migration\n ): Promise<void> {\n const checksum = calculateChecksum(migration);\n\n await adapter.insert(\"nextly_migrations\", {\n id: migration.id,\n name: migration.name,\n applied_at: new Date(),\n checksum,\n });\n },\n\n async removeMigrationRecord(\n adapter: DrizzleAdapter,\n migrationId: string\n ): Promise<void> {\n await adapter.delete(\"nextly_migrations\", {\n and: [{ column: \"id\", op: \"=\", value: migrationId }],\n });\n },\n\n async migrationsTableExists(adapter: DrizzleAdapter): Promise<boolean> {\n try {\n // Try to query the table - if it doesn't exist, this will throw\n await adapter.select(\"nextly_migrations\", { limit: 1 });\n return true;\n } catch {\n return false;\n }\n },\n};\n\n// ============================================================\n// Type Exports\n// ============================================================\n\n// Re-export migration types for convenience\nexport type {\n Migration,\n MigrationRecord,\n MigrationResult,\n MigrationStatus,\n MigrationOptions,\n} from \"./types/migration\";\n"]}
@@ -0,0 +1,351 @@
1
+ import { D as DrizzleAdapter } from './adapter-nvlxFkF-.cjs';
2
+ import { M as MigrationRecord, a as Migration, b as MigrationStatus, c as MigrationOptions } from './migration-BbO5meEV.cjs';
3
+ export { d as MigrationResult } from './migration-BbO5meEV.cjs';
4
+ import './core-CVO7WYDj.cjs';
5
+ import './schema-BDn8WfSL.cjs';
6
+ import './error-um1d_3Uo.cjs';
7
+
8
+ /**
9
+ * Database migration utilities.
10
+ *
11
+ * @remarks
12
+ * Provides core utilities for migration management including checksum calculation,
13
+ * sorting, filtering, and validation. Also includes optional helpers for adapters
14
+ * to use for common migration operations.
15
+ *
16
+ * @packageDocumentation
17
+ */
18
+
19
+ /**
20
+ * Calculate SHA-256 checksum for a migration.
21
+ *
22
+ * @remarks
23
+ * Creates a checksum of the entire migration object including id, name, timestamp,
24
+ * and the string representation of up/down functions. This allows detection of
25
+ * any changes to the migration after it has been applied.
26
+ *
27
+ * @param migration - Migration to calculate checksum for
28
+ * @returns Hexadecimal SHA-256 hash
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const migration: Migration = {
33
+ * id: "20250104_001_create_users",
34
+ * name: "Create users table",
35
+ * timestamp: 1704326400000,
36
+ * up: "CREATE TABLE users (id UUID PRIMARY KEY);",
37
+ * };
38
+ *
39
+ * const checksum = calculateChecksum(migration);
40
+ * // Returns: "a3f5b8c9d2e1f0..."
41
+ * ```
42
+ *
43
+ * @public
44
+ */
45
+ declare function calculateChecksum(migration: Migration): string;
46
+ /**
47
+ * Sort migrations by timestamp in ascending order.
48
+ *
49
+ * @remarks
50
+ * Provides deterministic ordering of migrations. If timestamps are equal,
51
+ * falls back to sorting by migration ID alphabetically.
52
+ *
53
+ * @param migrations - Array of migrations to sort
54
+ * @returns New sorted array (original array is not modified)
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const migrations = [
59
+ * { id: "003", timestamp: 1704412800000, ... },
60
+ * { id: "001", timestamp: 1704326400000, ... },
61
+ * { id: "002", timestamp: 1704326400000, ... },
62
+ * ];
63
+ *
64
+ * const sorted = sortMigrations(migrations);
65
+ * // Returns: [001, 002, 003] (001 and 002 same timestamp, sorted by id)
66
+ * ```
67
+ *
68
+ * @public
69
+ */
70
+ declare function sortMigrations(migrations: Migration[]): Migration[];
71
+ /**
72
+ * Filter migrations to get only pending (unapplied) migrations.
73
+ *
74
+ * @remarks
75
+ * Returns migrations that have not been applied to the database yet.
76
+ * A migration is considered pending if its ID is not present in the
77
+ * applied migration records.
78
+ *
79
+ * @param migrations - All available migrations
80
+ * @param applied - Records of applied migrations from database
81
+ * @returns Array of pending migrations
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const allMigrations = [
86
+ * { id: "001_create_users", ... },
87
+ * { id: "002_create_posts", ... },
88
+ * { id: "003_create_comments", ... },
89
+ * ];
90
+ *
91
+ * const appliedRecords = [
92
+ * { id: "001_create_users", appliedAt: new Date(), ... },
93
+ * ];
94
+ *
95
+ * const pending = filterPending(allMigrations, appliedRecords);
96
+ * // Returns: [002_create_posts, 003_create_comments]
97
+ * ```
98
+ *
99
+ * @public
100
+ */
101
+ declare function filterPending(migrations: Migration[], applied: MigrationRecord[]): Migration[];
102
+ /**
103
+ * Filter migration records to get only those that match given migrations.
104
+ *
105
+ * @remarks
106
+ * Returns applied migration records that correspond to the given migrations.
107
+ * Useful for getting the subset of applied records relevant to a specific
108
+ * set of migrations.
109
+ *
110
+ * @param migrations - Migrations to match
111
+ * @param applied - All applied migration records from database
112
+ * @returns Array of matching applied records
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const migrations = [
117
+ * { id: "001_create_users", ... },
118
+ * { id: "002_create_posts", ... },
119
+ * ];
120
+ *
121
+ * const allApplied = [
122
+ * { id: "001_create_users", appliedAt: new Date(), ... },
123
+ * { id: "002_create_posts", appliedAt: new Date(), ... },
124
+ * { id: "003_create_comments", appliedAt: new Date(), ... },
125
+ * ];
126
+ *
127
+ * const relevant = filterApplied(migrations, allApplied);
128
+ * // Returns: [001_create_users, 002_create_posts]
129
+ * ```
130
+ *
131
+ * @public
132
+ */
133
+ declare function filterApplied(migrations: Migration[], applied: MigrationRecord[]): MigrationRecord[];
134
+ /**
135
+ * Validate that a migration's checksum matches its applied record.
136
+ *
137
+ * @remarks
138
+ * Compares the calculated checksum of a migration against the stored checksum
139
+ * in its migration record. Returns false if checksums don't match or if the
140
+ * record has no checksum.
141
+ *
142
+ * @param migration - Migration to validate
143
+ * @param record - Applied migration record with stored checksum
144
+ * @returns true if checksums match, false otherwise
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const migration: Migration = { id: "001", ... };
149
+ * const record: MigrationRecord = {
150
+ * id: "001",
151
+ * checksum: "a3f5b8c9...",
152
+ * ...
153
+ * };
154
+ *
155
+ * const isValid = validateChecksum(migration, record);
156
+ * // Returns: true if checksums match, false if modified
157
+ * ```
158
+ *
159
+ * @public
160
+ */
161
+ declare function validateChecksum(migration: Migration, record: MigrationRecord): boolean;
162
+ /**
163
+ * Detect migrations that have been modified after being applied.
164
+ *
165
+ * @remarks
166
+ * Compares checksums of migrations against their applied records to detect
167
+ * any modifications. Returns records for migrations that have been changed
168
+ * since they were applied to the database.
169
+ *
170
+ * This is critical for detecting potentially dangerous situations where a
171
+ * migration that has already run has been modified.
172
+ *
173
+ * @param migrations - Current migrations
174
+ * @param applied - Applied migration records with checksums
175
+ * @returns Array of records for modified migrations
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const migrations = [{ id: "001", up: "CREATE TABLE users_v2 ..." }];
180
+ * const applied = [{ id: "001", checksum: "original_hash", ... }];
181
+ *
182
+ * const modified = detectModified(migrations, applied);
183
+ * // Returns: [{ id: "001", ... }] if migration was changed
184
+ * ```
185
+ *
186
+ * @public
187
+ */
188
+ declare function detectModified(migrations: Migration[], applied: MigrationRecord[]): MigrationRecord[];
189
+ /**
190
+ * Get comprehensive migration status.
191
+ *
192
+ * @remarks
193
+ * Analyzes migrations and applied records to produce a complete status report
194
+ * including current migration, applied/pending counts, and full lists.
195
+ *
196
+ * @param migrations - All available migrations
197
+ * @param applied - Applied migration records from database
198
+ * @returns Complete migration status information
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * const status = getMigrationStatus(allMigrations, appliedRecords);
203
+ * console.log(`Current: ${status.current}`);
204
+ * console.log(`Applied: ${status.appliedCount}, Pending: ${status.pendingCount}`);
205
+ * ```
206
+ *
207
+ * @public
208
+ */
209
+ declare function getMigrationStatus(migrations: Migration[], applied: MigrationRecord[]): MigrationStatus;
210
+ /**
211
+ * Validation result for migrations.
212
+ *
213
+ * @public
214
+ */
215
+ interface MigrationValidationResult {
216
+ /** Whether all validations passed */
217
+ valid: boolean;
218
+ /** List of validation errors */
219
+ errors: string[];
220
+ /** List of validation warnings */
221
+ warnings: string[];
222
+ /** Migrations that have been modified */
223
+ modified: MigrationRecord[];
224
+ /** Duplicate migration IDs found */
225
+ duplicates: string[];
226
+ }
227
+ /**
228
+ * Validate migrations for common issues.
229
+ *
230
+ * @remarks
231
+ * Performs comprehensive validation including:
232
+ * - Duplicate migration IDs
233
+ * - Modified applied migrations (checksum mismatch)
234
+ * - Missing required fields
235
+ * - Invalid timestamps
236
+ *
237
+ * @param migrations - Migrations to validate
238
+ * @param applied - Applied migration records (for checksum validation)
239
+ * @param options - Migration options (for strictness configuration)
240
+ * @returns Validation result with errors and warnings
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * const result = validateMigrations(migrations, applied, {
245
+ * strictChecksums: true
246
+ * });
247
+ *
248
+ * if (!result.valid) {
249
+ * console.error("Validation errors:", result.errors);
250
+ * throw new Error("Migration validation failed");
251
+ * }
252
+ * ```
253
+ *
254
+ * @public
255
+ */
256
+ declare function validateMigrations(migrations: Migration[], applied: MigrationRecord[], options?: MigrationOptions): MigrationValidationResult;
257
+ /**
258
+ * Helper functions for managing migrations in database adapters.
259
+ *
260
+ * @remarks
261
+ * These helpers reduce boilerplate code in dialect-specific adapters by
262
+ * providing common operations like creating migration tables, recording
263
+ * migrations, and querying migration status.
264
+ *
265
+ * Adapters can use these helpers or implement their own logic.
266
+ *
267
+ * @public
268
+ */
269
+ interface MigrationHelpers {
270
+ /**
271
+ * Create the migrations tracking table if it doesn't exist.
272
+ *
273
+ * @remarks
274
+ * Creates a table named `nextly_migrations` with columns:
275
+ * - id (string, primary key)
276
+ * - name (string)
277
+ * - applied_at (timestamp)
278
+ * - checksum (string, optional)
279
+ *
280
+ * Uses CREATE TABLE IF NOT EXISTS for safety.
281
+ *
282
+ * @param adapter - Database adapter to use
283
+ * @returns Promise that resolves when table is created
284
+ */
285
+ createMigrationsTable(adapter: DrizzleAdapter): Promise<void>;
286
+ /**
287
+ * Get all applied migration records from the database.
288
+ *
289
+ * @remarks
290
+ * Queries the `nextly_migrations` table and returns all records
291
+ * sorted by applied_at descending (most recent first).
292
+ *
293
+ * @param adapter - Database adapter to use
294
+ * @returns Promise with array of applied migration records
295
+ */
296
+ getAppliedMigrations(adapter: DrizzleAdapter): Promise<MigrationRecord[]>;
297
+ /**
298
+ * Record a migration as applied in the database.
299
+ *
300
+ * @remarks
301
+ * Inserts a new record into the `nextly_migrations` table with:
302
+ * - Migration ID, name
303
+ * - Current timestamp for applied_at
304
+ * - Calculated checksum
305
+ *
306
+ * Should be called within a transaction during migration execution.
307
+ *
308
+ * @param adapter - Database adapter to use
309
+ * @param migration - Migration that was applied
310
+ * @returns Promise that resolves when record is inserted
311
+ */
312
+ recordMigration(adapter: DrizzleAdapter, migration: Migration): Promise<void>;
313
+ /**
314
+ * Remove a migration record from the database.
315
+ *
316
+ * @remarks
317
+ * Deletes a record from the `nextly_migrations` table.
318
+ * Used during migration rollback operations.
319
+ *
320
+ * Should be called within a transaction during rollback.
321
+ *
322
+ * @param adapter - Database adapter to use
323
+ * @param migrationId - ID of the migration to remove
324
+ * @returns Promise that resolves when record is deleted
325
+ */
326
+ removeMigrationRecord(adapter: DrizzleAdapter, migrationId: string): Promise<void>;
327
+ /**
328
+ * Check if migrations table exists.
329
+ *
330
+ * @remarks
331
+ * Queries database metadata to check if the `nextly_migrations` table exists.
332
+ * Useful for determining if initialization is needed.
333
+ *
334
+ * @param adapter - Database adapter to use
335
+ * @returns Promise with boolean indicating if table exists
336
+ */
337
+ migrationsTableExists(adapter: DrizzleAdapter): Promise<boolean>;
338
+ }
339
+ /**
340
+ * Implementation of migration helpers.
341
+ *
342
+ * @remarks
343
+ * Provides default implementations using the adapter's query methods.
344
+ * These work across all dialects but adapters can optimize for their
345
+ * specific database if needed.
346
+ *
347
+ * @public
348
+ */
349
+ declare const migrationHelpers: MigrationHelpers;
350
+
351
+ export { Migration, type MigrationHelpers, MigrationOptions, MigrationRecord, MigrationStatus, type MigrationValidationResult, calculateChecksum, detectModified, filterApplied, filterPending, getMigrationStatus, migrationHelpers, sortMigrations, validateChecksum, validateMigrations };