tj / node-migrate

Abstract migration framework for node
MIT License
1.53k stars 221 forks source link

Why does a custom store need an `up` function? #183

Closed g14a closed 3 years ago

g14a commented 3 years ago

Hello. I'm trying to have a Mongo collection as a custom store for migrations and my store looks like below:

custom-store.js


const url = 'mongodb://localhost/sampledb'
const mongodb = require('mongodb')
const MongoClient = mongodb.MongoClient

class MongoDbStore {
    async load(fn) {
        let client = null
        let data = null
        try {
            client = await MongoClient.connect(url)
            const db = client.db()
            data = await db.collection('migrations').find().toArray()
            if (data.length !== 1) {
                console.log('Cannot read migrations from database. If this is the first time you run migrations, then this is normal.')
                return fn(null, {})
            }
        } catch (err) {
            throw err
        } finally {
            client.close()
        }
        return fn(null, data[0])
    };

    async save(set, fn) {
        let client = null
        let result = null
        try {
            client = await MongoClient.connect(url)
            const db = client.db()
            result = await db.collection('migrations')
                .updateOne({}, {
                    $set: {
                        lastRun: set.lastRun
                    },
                    $push: {
                        migrations: { $each: set.migrations }
                    }
                }, { upsert: true })
        } catch (err) {
            throw err
        } finally {
            client.close()
        }

        return fn(null, result)
    }
}

module.exports = MongoDbStore

And my seed file is of the type 1606969258851-add-name.js which just has an up function just for testing purposes:

module.exports.up = function (next) {
  let mClient = null
  return MongoClient.connect(url).
    then(client => {
      mClient = client
      return client.db()
    })
    .then(db => {
      const pets = db.collection('pets')
      pets.insertMany([{ "name": "gowtham" }, { "name": "chaitu" }]);
    }).then(() => {
      mClient.close()
      return next()
    })
    .catch(err => next(err))
}

I'm using the command line interface and when I run

./node_modules/migrate/bin/migrate up --store=./migrations/custom-store.js

I get the following error:

node:14395) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
  error : TypeError: Migration custom-store.js does not have method up
TypeError: Migration custom-store.js does not have method up
    at next (/Users/g14a/service/node_modules/migrate/lib/migrate.js:26:17)
    at migrate (/Users/g14a/service/node_modules/migrate/lib/migrate.js:76:3)
    at up (/Users/g14a/service/node_modules/migrate/bin/migrate-up:119:3)
    at /Users/g14a/service/node_modules/migrate/bin/migrate-up:98:36
    at /Users/g14a/service/node_modules/migrate/index.js:61:5
    at /Users/g14a/service/node_modules/migrate/lib/load-migrations.js:72:7
    at FSReqCallback.oncomplete (fs.js:156:23)

My question is why does a custom store engine need an up method? I thought all it needs is load and save. Thank you.

@wesleytodd

g14a commented 3 years ago

@tj @wesleytodd did anyone have time to look at this?

g14a commented 3 years ago

I solved it. My custom-store file was inside the migrations directory. Sorry to bother ya'll.

wesleytodd commented 3 years ago

Hey, sorry for the lack of response (on holiday). Any file in the migrations directory is treated as a migration to run, so yes your solution works.

Another option is to use the filterFunction option to filter out your store file. That can be passed as a glob pattern on the cli via the --matches flag. Hope that helps.