Database Schema Updater
database-updates is a Node.js library designed to manage and apply database schema and data migration scripts in a versioned, reliable manner. It is currently at version 4.1.0 and appears to be actively maintained, though no explicit release cadence is stated beyond following semantic versioning for its own releases. The core differentiator is its reliance on SemVer (Semantic Versioning) compliant filenames for update scripts (e.g., `1.0.0-initial-setup.js`), which dictates the execution order and ensures each script runs exactly once per environment. This mechanism prevents inconsistencies across development, staging, and production environments. It supports both CommonJS and ES Module update scripts and offers experimental support for TypeScript update files, provided the runtime can dynamically `import()` them. It's particularly useful for applications built on MongoDB or similar NoSQL databases where schema changes are often handled via code-based migrations.
Common errors
-
Error: Cannot find module 'path/to/my-update.ts' or SyntaxError: Cannot use import statement outside a module
cause Attempting to use a `.ts` update script without configuring the Node.js runtime to handle TypeScript files, or trying to `require()` an ESM-style `.ts` file in a CJS context.fixIf using `.ts` files, ensure `ts-node` is installed and registered (e.g., `node -r ts-node/register your-app.js`) or transpile your `.ts` files to `.js` before running. For ESM `.ts` files, ensure your project is configured for ESM (e.g., `"type": "module"` in `package.json`) and you're using dynamic `import()` where necessary. -
Error: Update script 'path/to/0.0.1-my-update.js' did not export a function
cause The update script file does not have the expected function export (`module.exports = function(db){}` or `export default function(db){}`).fixReview the update script file to ensure it exports a function with the `(db)` signature correctly. Check for typos in `module.exports` or `export default`. -
MongoError: not master and slaveOk=false
cause This error occurs when attempting to perform write operations (like creating collections or indexes) on a MongoDB replica set secondary member without appropriate write concerns or read preferences.fixEnsure your database connection is directed to the primary replica set member for write operations, or configure appropriate write concerns and read preferences for your `MongoClient` instance if you intend to write to secondaries (which is generally not recommended for migrations).
Warnings
- gotcha TypeScript support is explicitly experimental. It relies on your runtime's ability to dynamically `import()` `.ts` files, which typically requires a specific setup (e.g., using `ts-node` or a custom module loader) and may not work out-of-the-box in standard Node.js environments.
- breaking Update script filenames MUST adhere strictly to Semantic Versioning (SemVer) followed by a dash and description (e.g., `X.Y.Z-description.js`). Incorrect naming will result in scripts not being run or executed in an unexpected order.
- gotcha Each update script must export a function that accepts the database connection as its first and only argument. This function can be synchronous, asynchronous, or return a Promise. Incorrect export signatures will prevent the script from running.
- gotcha An update script, once successfully run, will never be executed again on the same machine/environment. The applied updates are recorded in a configurable collection (default `databaseUpdates`). If an update needs to be re-run, a new versioned script must be created, or the entry manually removed from the `databaseUpdates` collection.
Install
-
npm install database-updates -
yarn add database-updates -
pnpm add database-updates
Imports
- databaseUpdates
const databaseUpdates = require('database-updates').defaultimport databaseUpdates from 'database-updates'
- databaseUpdates (CommonJS)
const databaseUpdates = require('database-updates') - DatabaseUpdates (class constructor)
const { DatabaseUpdates } = require('database-updates').defaultimport { DatabaseUpdates } from 'database-updates'
Quickstart
const { MongoClient } = require('mongodb')
const databaseUpdates = require('database-updates')
async function main() {
const client = await MongoClient.connect(
'mongodb://localhost/database-updates-example',
{ useNewUrlParser: true, useUnifiedTopology: true } // Add options for modern MongoClient
)
// Optional: Drop the database for a clean run in development
await client.db().dropDatabase()
// Define a simple update script path for demonstration
const updateScriptPath = `${__dirname}/temp_updates`
require('fs').mkdirSync(updateScriptPath, { recursive: true })
require('fs').writeFileSync(
`${updateScriptPath}/0.0.1-initial-collection.js`,
`module.exports = async (db) => {
await db.createCollection('users')
console.log('Created users collection.')
}`
)
console.log('Applying database updates...')
await databaseUpdates({
db: client.db(),
updatePath: updateScriptPath,
logger: console
}).run()
console.log('Done! Check your MongoDB instance for the "users" collection.')
return client.close()
}
main().catch((e) => {
console.error('An error occurred:', e)
process.exit(1)
})