migrate-mongo
Advanced tools
+11
-0
@@ -7,2 +7,13 @@ # Changelog | ||
| ## [14.0.0] - TBD | ||
| - **BREAKING**: Remove callback-based migration support | ||
| - Migrations must now use Promises or async/await | ||
| - The `up(db, client, callback)` and `down(db, client, callback)` signatures are no longer supported | ||
| - Use `async function up(db, client)` or return a Promise instead | ||
| - Remove fn-args dependency (reduces production dependencies from 4 to 3) | ||
| - Simplify migration execution code | ||
| - Remove deprecated `useNewUrlParser` and `useUnifiedTopology` options from sample config files | ||
| - These options are no longer supported in MongoDB driver 4.x+ and will cause errors | ||
| - Generated config files now have these commented out with explanatory notes | ||
| ## [13.0.1] - 2025-12-02 | ||
@@ -9,0 +20,0 @@ - Remove -md from README, this option does not exist |
+1
-18
@@ -1,16 +0,7 @@ | ||
| const { promisify } = require("util"); | ||
| const status = require("./status"); | ||
| const config = require("../env/config"); | ||
| const migrationsDir = require("../env/migrationsDir"); | ||
| const hasCallback = require("../utils/has-callback"); | ||
| const lock = require("../utils/lock"); | ||
| async function loadFnArgs() { | ||
| const module = await import('fn-args'); | ||
| return module.default; | ||
| } | ||
| module.exports = async (db, client) => { | ||
| const fnArgsFunc = await loadFnArgs(); | ||
| const isBlockRollback = global.options?.block; | ||
@@ -34,12 +25,4 @@ const downgraded = []; | ||
| const migration = await migrationsDir.loadMigration(item.fileName); | ||
| const isCallback = await hasCallback(migration.down); | ||
| const down = isCallback ? promisify(migration.down) : migration.down; | ||
| await migration.down(db, client); | ||
| if (isCallback && fnArgsFunc(migration.down).length < 3) { | ||
| // support old callback-based migrations prior to migrate-mongo 7.x.x | ||
| await down(db); | ||
| } else { | ||
| await down(db, client); | ||
| } | ||
| } catch (err) { | ||
@@ -46,0 +29,0 @@ throw new Error( |
+1
-18
@@ -1,16 +0,7 @@ | ||
| const { promisify } = require("util"); | ||
| const status = require("./status"); | ||
| const config = require("../env/config"); | ||
| const migrationsDir = require("../env/migrationsDir"); | ||
| const hasCallback = require("../utils/has-callback"); | ||
| const lock = require("../utils/lock"); | ||
| async function loadFnArgs() { | ||
| const module = await import('fn-args'); | ||
| return module.default; | ||
| } | ||
| module.exports = async (db, client) => { | ||
| const fnArgsFunc = await loadFnArgs(); | ||
| const statusItems = await status(db); | ||
@@ -34,12 +25,4 @@ const pendingItems = statusItems.filter(item => item.appliedAt === "PENDING"); | ||
| const migration = await migrationsDir.loadMigration(item.fileName); | ||
| const isCallback = await hasCallback(migration.up); | ||
| const up = isCallback ? promisify(migration.up) : migration.up; | ||
| await migration.up(db, client); | ||
| if (isCallback && fnArgsFunc(migration.up).length < 3) { | ||
| // support old callback-based migrations prior to migrate-mongo 7.x.x | ||
| await up(db); | ||
| } else { | ||
| await up(db, client); | ||
| } | ||
| } catch (err) { | ||
@@ -46,0 +29,0 @@ const error = new Error( |
+1
-2
| { | ||
| "name": "migrate-mongo", | ||
| "version": "13.0.2", | ||
| "version": "14.0.0", | ||
| "description": "A database migration tool for MongoDB in Node", | ||
@@ -30,3 +30,2 @@ "main": "lib/migrate-mongo.js", | ||
| "commander": "^14.0.2", | ||
| "fn-args": "^6.0.0", | ||
| "fs-extra": "^11.3.2" | ||
@@ -33,0 +32,0 @@ }, |
+4
-23
@@ -155,6 +155,5 @@ <p align="center"> | ||
| There are 3 options to implement the `up` and `down` functions of your migration: | ||
| 1. Return a Promises | ||
| 2. Use async-await | ||
| 3. Call a callback ⚠️ **DEPRECATED - Use Promises or async/await instead** | ||
| There are 2 ways to implement the `up` and `down` functions of your migration: | ||
| 1. Return a Promise | ||
| 2. Use async-await (recommended) | ||
@@ -164,3 +163,2 @@ Always make sure the implementation matches the function signature: | ||
| * `async function up(db, client) { /* */ }` should contain `await` keyword(s) and return `Promise` | ||
| * `function up(db, client, next) { /* */ }` should callback `next` | ||
@@ -180,3 +178,3 @@ #### Example 1: Return a Promise | ||
| #### Example 2: Use async & await | ||
| #### Example 2: Use async & await (recommended) | ||
| Async & await is especially useful if you want to perform multiple operations against your MongoDB in one migration. | ||
@@ -198,19 +196,2 @@ | ||
| #### Example 3: Call a callback ⚠️ DEPRECATED | ||
| **⚠️ Callbacks are deprecated.** New migration scripts should use Promises or async/await. | ||
| Callbacks are supported for backwards compatibility only. They're harder to read and write compared to modern async patterns. | ||
| ````javascript | ||
| module.exports = { | ||
| up(db, callback) { | ||
| return db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: true}}, callback); | ||
| }, | ||
| down(db, callback) { | ||
| return db.collection('albums').updateOne({artist: 'The Beatles'}, {$set: {blacklisted: false}}, callback); | ||
| } | ||
| }; | ||
| ```` | ||
| #### Overriding the sample migration | ||
@@ -217,0 +198,0 @@ To override the content of the sample migration that will be created by the `create` command, |
@@ -12,4 +12,4 @@ // In this file you can configure migrate-mongo | ||
| options: { | ||
| useNewUrlParser: true, // removes a deprecation warning when connecting | ||
| useUnifiedTopology: true, // removes a deprecating warning when connecting | ||
| // useNewUrlParser: true, // (not needed anymore in mongodb driver 4.x+) | ||
| // useUnifiedTopology: true, // (not needed anymore in mongodb driver 4.x+) | ||
| // connectTimeoutMS: 3600000, // increase connection timeout to 1 hour | ||
@@ -16,0 +16,0 @@ // socketTimeoutMS: 3600000, // increase socket timeout to 1 hour |
@@ -12,4 +12,4 @@ // In this file you can configure migrate-mongo | ||
| options: { | ||
| useNewUrlParser: true, // removes a deprecation warning when connecting | ||
| useUnifiedTopology: true, // removes a deprecating warning when connecting | ||
| // useNewUrlParser: true, // (not needed anymore in mongodb driver 4.x+) | ||
| // useUnifiedTopology: true, // (not needed anymore in mongodb driver 4.x+) | ||
| // connectTimeoutMS: 3600000, // increase connection timeout to 1 hour | ||
@@ -35,3 +35,3 @@ // socketTimeoutMS: 3600000, // increase socket timeout to 1 hour | ||
| // Enable the algorithm to create a checksum of the file contents and use that in the comparison to determin | ||
| // Enable the algorithm to create a checksum of the file contents and use that in the comparison to determine | ||
| // if the file should be run. Requires that scripts are coded to be run multiple times. | ||
@@ -38,0 +38,0 @@ useFileHash: false, |
@@ -154,24 +154,2 @@ const { expect } = require("chai"); | ||
| it("should be able to downgrade callback based migration that has both the `db` and `client` arguments", async () => { | ||
| migration = { | ||
| down(theDb, theClient, callback) { | ||
| return callback(); | ||
| } | ||
| }; | ||
| migrationsDir = mockMigrationsDir(); | ||
| down = loadDownWithInjectedMocks(); | ||
| await down(db, client); | ||
| }); | ||
| it("should be able to downgrade callback based migration that has only the `db` argument", async () => { | ||
| migration = { | ||
| down(theDb, callback) { | ||
| return callback(); | ||
| } | ||
| }; | ||
| migrationsDir = mockMigrationsDir(); | ||
| down = loadDownWithInjectedMocks(); | ||
| await down(db); | ||
| }); | ||
| /* eslint no-unused-vars: "off" */ | ||
@@ -178,0 +156,0 @@ it("should allow downgrade to return promise", async () => { |
@@ -162,24 +162,2 @@ const { expect } = require("chai"); | ||
| it("should be able to upgrade callback based migration that has both the `db` and `client` args", async () => { | ||
| firstPendingMigration = { | ||
| up(theDb, theClient, callback) { | ||
| return callback(); | ||
| } | ||
| }; | ||
| migrationsDir = mockMigrationsDir(); | ||
| up = loadUpWithInjectedMocks(); | ||
| await up(db, client); | ||
| }); | ||
| it("should be able to upgrade callback based migration that has only the `db` arg", async () => { | ||
| firstPendingMigration = { | ||
| up(theDb, callback) { | ||
| return callback(); | ||
| } | ||
| }; | ||
| migrationsDir = mockMigrationsDir(); | ||
| up = loadUpWithInjectedMocks(); | ||
| await up(db, client); | ||
| }); | ||
| it("should populate the changelog with info about the upgraded migrations", async () => { | ||
@@ -186,0 +164,0 @@ const clock = sinon.useFakeTimers( |
| let fnArgs; | ||
| async function loadFnArgs() { | ||
| if (!fnArgs) { | ||
| const module = await import('fn-args'); | ||
| fnArgs = module.default; | ||
| } | ||
| return fnArgs; | ||
| } | ||
| module.exports = async (func) => { | ||
| const fnArgsFunc = await loadFnArgs(); | ||
| const argNames = fnArgsFunc(func); | ||
| const lastArgName = argNames[argNames.length - 1]; | ||
| return [ | ||
| 'callback', | ||
| 'callback_', | ||
| 'cb', | ||
| 'cb_', | ||
| 'next', | ||
| 'next_', | ||
| 'done', | ||
| 'done_' | ||
| ].includes(lastArgName); | ||
| }; |
| const { expect } = require("chai"); | ||
| const hasCallback = require('../../lib/utils/has-callback'); | ||
| describe('has-callback', () => { | ||
| it('should return true when last argument is called `callback`', async () => { | ||
| expect(await hasCallback((db, callback) => { | ||
| return callback(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `callback_`', async () => { | ||
| expect(await hasCallback((db, callback_) => { | ||
| return callback_(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `cb`', async () => { | ||
| expect(await hasCallback((db, cb) => { | ||
| return cb(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `cb_`', async () => { | ||
| expect(await hasCallback((db, cb_) => { | ||
| return cb_(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `next`', async () => { | ||
| expect(await hasCallback((db, next) => { | ||
| return next(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `next_`', async () => { | ||
| expect(await hasCallback((db, next_) => { | ||
| return next_(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `done`', async () => { | ||
| expect(await hasCallback((db, done) => { | ||
| return done(); | ||
| })).to.equal(true); | ||
| }); | ||
| it('should return true when last argument is called `done_`', async () => { | ||
| expect(await hasCallback((db, done_) => { | ||
| return done_(); | ||
| })).to.equal(true); | ||
| }); | ||
| }); |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
4
-20%127096
-3.41%37
-5.13%2313
-5.51%505
-3.63%- Removed
- Removed