Skip to content

Instantly share code, notes, and snippets.

@atharrison
Created September 4, 2025 23:50
Show Gist options
  • Select an option

  • Save atharrison/09072d5a20f28c34279c5d3142ac860a to your computer and use it in GitHub Desktop.

Select an option

Save atharrison/09072d5a20f28c34279c5d3142ac860a to your computer and use it in GitHub Desktop.
Format Prisma Migrations. Remove "public" schema that is auto-included since Prisma 6.13.0
import fs from 'fs'
import path from 'path'
/**
* Configuration object for migration formatting
* This can be easily overridden when used as a shared library
*/
export interface Pattern {
from: RegExp
to: string
}
export interface Config {
migrationsDir?: string
patterns?: Pattern[]
}
export interface FormatResult {
cleanedCount: number
totalCount: number
cleanedFiles: string[]
}
export const DEFAULT_CONFIG: Required<Config> = {
migrationsDir: path.join(__dirname, '../prisma/migrations'),
patterns: [
{ from: /"public"\."/g, to: '"' }, // Remove "public". prefixes
// Add more patterns here as needed
],
}
/**
* Formats migration files by applying configured patterns
* @param config - Configuration object
* @returns Result with counts and details
*/
export function formatMigrationFiles(config: Config = {}): FormatResult {
const finalConfig = { ...DEFAULT_CONFIG, ...config }
const { migrationsDir, patterns } = finalConfig
console.log('🧹 Formatting Prisma migration files...')
if (!fs.existsSync(migrationsDir)) {
console.log('No migrations directory found, skipping...')
return { cleanedCount: 0, totalCount: 0, cleanedFiles: [] }
}
const migrationDirs = fs
.readdirSync(migrationsDir, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name)
let cleanedCount = 0
let totalCount = 0
const cleanedFiles: string[] = []
migrationDirs.forEach(dir => {
const migrationPath = path.join(migrationsDir, dir)
const sqlFile = path.join(migrationPath, 'migration.sql')
if (fs.existsSync(sqlFile)) {
totalCount++
let content = fs.readFileSync(sqlFile, 'utf8')
const originalContent = content
// Apply all configured patterns
patterns.forEach(pattern => {
content = content.replace(pattern.from, pattern.to)
})
// Only write if content actually changed
if (content !== originalContent) {
fs.writeFileSync(sqlFile, content)
cleanedCount++
cleanedFiles.push(`${dir}/migration.sql`)
console.log(`✅ Formatted: prisma/migrations/${dir}/migration.sql`)
}
}
})
if (cleanedCount > 0) {
console.log(
`\n🎉 Successfully formatted ${cleanedCount} out of ${totalCount} migration files in prisma/migrations/`
)
} else {
console.log(
`\n✨ All ${totalCount} migration files in prisma/migrations/ are already properly formatted`
)
}
return { cleanedCount, totalCount, cleanedFiles }
}
/**
* CLI entry point
*/
function main(): void {
try {
formatMigrationFiles()
} catch (error) {
console.error(
'❌ Error formatting migration files:',
(error as Error).message
)
process.exit(1)
}
}
// Run the script if called directly
if (require.main === module) {
main()
}
@atharrison
Copy link
Author

I have an npm command to run prisma migrate, and now I add this format as a post-processing step:

    "prisma:local:migrate:dev": "dotenvx run -f .env -- prisma migrate dev",
    "postprisma:local:migrate:dev": "ts-node scripts/format-migrations.ts",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment