{"id":16641,"library":"marv","title":"Marv","description":"Marv is a programmatic database migration tool designed for Node.js environments, offering a flexible, driver-based approach to managing schema changes. Currently stable at version 6.1.0, it supports a wide range of relational databases including MySQL, PostgreSQL, SQLite, Microsoft SQL Server, and Oracle DB through dedicated pluggable drivers (e.g., `marv-pg-driver`). It distinguishes itself by providing both Promise and Callback-based APIs for integration into various application architectures. Marv's core functionality involves scanning a directory for SQL migration files, validating their sequence, and applying them to the target database. It enforces strict ordering, reporting errors for duplicate levels or out-of-sequence execution, which necessitates careful branching strategies when developing new migrations. Releases appear to follow a semantic versioning approach, with major versions introducing significant changes.","status":"active","version":"6.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/guidesmiths/marv","tags":["javascript","marv","database","db","migration","migrate","postgres","postgresql","mysql"],"install":[{"cmd":"npm install marv","lang":"bash","label":"npm"},{"cmd":"yarn add marv","lang":"bash","label":"yarn"},{"cmd":"pnpm add marv","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for PostgreSQL database migrations.","package":"marv-pg-driver","optional":false},{"reason":"Required for MySQL database migrations.","package":"marv-mysql-driver","optional":false},{"reason":"Required for SQLite database migrations.","package":"@open-fidias/marv-better-sqlite3-driver","optional":false},{"reason":"Required for Microsoft SQL Server database migrations.","package":"@infinitaslearning/marv-mssql-driver","optional":false},{"reason":"Required for Oracle DB database migrations.","package":"marv-oracledb-driver","optional":false}],"imports":[{"note":"Marv exports its API as a default CommonJS object from specific paths. The promise-based API is accessed via `marv/api/promise`. Destructuring like `const { scan } = require('marv/api/promise');` is incorrect as the module exports a single object, not named properties. Direct ESM `import` is not natively supported without a CJS wrapper or bundler due to the package's CommonJS module type.","wrong":"import marv from 'marv/api/promise';","symbol":"marv (Promise API)","correct":"const marv = require('marv/api/promise');"},{"note":"Similar to the promise API, the callback-based API is accessed via `marv/api/callback` using CommonJS `require`.","wrong":"import marv from 'marv/api/callback';","symbol":"marv (Callback API)","correct":"const marv = require('marv/api/callback');"},{"note":"Database drivers like `marv-pg-driver` are separate packages and must be installed alongside `marv`. They typically export a default function via CommonJS `require`.","wrong":"import pgDriver from 'marv-pg-driver';","symbol":"marv-pg-driver","correct":"const pgDriver = require('marv-pg-driver');"}],"quickstart":{"code":"const path = require('path');\nconst marv = require('marv/api/promise');\nconst pgDriver = require('marv-pg-driver');\n\nconst migrationsDirectory = path.resolve(__dirname, 'migrations');\n\n// Create a dummy migrations directory and file for demonstration\nconst fs = require('fs');\nif (!fs.existsSync(migrationsDirectory)) {\n  fs.mkdirSync(migrationsDirectory);\n}\nconst migrationFile = path.join(migrationsDirectory, '001.create-test-table.sql');\nif (!fs.existsSync(migrationFile)) {\n  fs.writeFileSync(migrationFile, 'CREATE TABLE IF NOT EXISTS test_table (id SERIAL PRIMARY KEY, name VARCHAR(255));');\n}\n\nasync function runMigrations() {\n  try {\n    // Placeholder for actual PostgreSQL connection details\n    const connection = {\n      host: process.env.DB_HOST ?? 'localhost',\n      port: parseInt(process.env.DB_PORT ?? '5432', 10),\n      user: process.env.DB_USER ?? 'postgres',\n      password: process.env.DB_PASSWORD ?? 'password',\n      database: process.env.DB_NAME ?? 'mydatabase',\n      // Optional: ssl: { rejectUnauthorized: false } for local testing if needed\n    };\n\n    const migrations = await marv.scan(migrationsDirectory);\n    await marv.migrate(migrations, pgDriver({ connection }));\n    console.log('Migrations applied successfully!');\n  } catch (err) {\n    console.error('Migration failed:', err.message);\n    process.exit(1);\n  }\n}\n\nrunMigrations();\n","lang":"javascript","description":"This quickstart demonstrates how to use Marv with its Promise API and a PostgreSQL driver to scan for and apply migrations from a local directory. It includes boilerplate for database connection configuration and creates a sample migration file if none exists for immediate execution."},"warnings":[{"fix":"Ensure all SQL migration scripts are idempotent. For example, use `CREATE TABLE IF NOT EXISTS` instead of `CREATE TABLE` where applicable. Plan for manual rollback/cleanup strategies for non-idempotent operations.","message":"Marv deliberately does not run migration scripts within a transaction. This means that if a script fails mid-execution, partial changes may be applied, and manual cleanup might be required. It is strongly recommended to make migration scripts idempotent (e.g., using `CREATE TABLE IF NOT EXISTS`).","severity":"gotcha","affected_versions":">=4.0.0"},{"fix":"Adopt a clear branching and merge strategy for migrations (e.g., rebase and renumber migrations before merging). Ensure migration filenames adhere to the `<level><separator><comment>.<extension>` format with unique numeric levels. Manually resolve ordering conflicts before running migrations.","message":"Marv enforces a strict sequential order for migrations. Attempting to run migrations with duplicate numeric levels or running migrations out of their detected sequence will result in errors. This has implications for branching strategies where multiple developers might create migrations concurrently.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Always install the appropriate `marv-*` driver package for your database (e.g., `npm install marv-pg-driver`). Check the `marv` documentation for the correct driver name.","message":"Marv requires a specific database driver package (e.g., `marv-pg-driver`, `marv-mysql-driver`) to be installed alongside it. Forgetting to install the correct driver for your target database will lead to runtime errors when attempting to connect or migrate.","severity":"gotcha","affected_versions":">=4.0.0"},{"fix":"Install `mysql2` alongside `marv-mysql-driver` (`npm install mysql2`), as `marv-mysql-driver` will automatically use it. Alternatively, configure your MySQL 8.0 server to use `mysql_native_password` as the default authentication plugin.","message":"When using `marv-mysql-driver` with MySQL 8.0+, you may encounter authentication issues because MySQL 8.0 changed its default authentication plugin to `caching_sha2_password`. The underlying `mysql` library might not support this, requiring `mysql2` or a server configuration change.","severity":"gotcha","affected_versions":">=4.0.0 (when using `marv-mysql-driver` with MySQL 8.0+)"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Rename one of the conflicting migration files to ensure all numeric levels are unique within the migrations directory.","cause":"Two or more migration files have the same numeric level in their filenames, which violates Marv's strict ordering requirement.","error":"Error: Duplicate migration level detected: [level] - [filename1] and [filename2]"},{"fix":"Investigate the database history to understand which migration was skipped or run incorrectly. If necessary, manually revert the database to a consistent state, or adjust the schema history table (if safe) to reflect the actual applied migrations, then re-run. Ensure migration files are applied in strict ascending order of their levels.","cause":"A migration script was detected that should have been run earlier based on its numeric level but was not, indicating an inconsistent database state or a deployment issue.","error":"Error: Migration [level] has been run out of sequence."},{"fix":"Install the correct Marv driver package for your database using npm, e.g., `npm install marv-pg-driver` or `npm install marv-mysql-driver`.","cause":"The specific database driver package required by Marv for your chosen database (e.g., PostgreSQL, MySQL) has not been installed.","error":"Error: Cannot find module 'marv-pg-driver' (or similar for other drivers)"}],"ecosystem":"npm"}