east-mongo
Advanced tools
Comparing version 0.3.6 to 1.0.0
'use strict'; | ||
var MongoClient = require('mongodb').MongoClient, | ||
path = require('path'), | ||
mongodbUri = require('mongodb-uri'), | ||
helpers = require('./helpers'); | ||
const MongoClient = require('mongodb').MongoClient; | ||
const mongodbPackageJson = require('mongodb/package.json'); | ||
const path = require('path'); | ||
const helpers = require('./helpers'); | ||
const mongodbMajor = Number(mongodbPackageJson.version.split('.')[0]); | ||
function Adapter(params) { | ||
@@ -18,75 +20,64 @@ this.params = params || {}; | ||
Adapter.prototype.getTemplatePath = function() { | ||
return path.join(__dirname, 'migrationTemplate.js'); | ||
Adapter.prototype.getTemplatePath = function getTemplatePath() { | ||
return path.join(__dirname, 'migrationTemplates', 'promises.js'); | ||
}; | ||
// mongodb driver 2.x passes `db`, 3.x passes `client` to the | ||
// `MongoClient.connect` callback this method sets clitnt and db | ||
// parsed from this polymorphic parameter | ||
Adapter.prototype._setDbAndClient = function(dbOrClient) { | ||
if (dbOrClient.collection) { | ||
this.client = null; | ||
// mongodb driver 2.x returns `db`, 3.x returns `client` as a result of | ||
// `MongoClient.connect`, this method sets client and db parsed from that | ||
// polymorphic result | ||
Adapter.prototype._setDbAndClient = function _setDbAndClient(connectResult) { | ||
if (mongodbMajor > 2) { | ||
this.client = connectResult; | ||
this.db = dbOrClient; | ||
// `db` without args gets db from uri ("test" if no db at uri) | ||
this.db = this.client.db(); | ||
} else { | ||
this.client = dbOrClient; | ||
this.client = null; | ||
var parsedUrl = mongodbUri.parse(this.params.url); | ||
var dbName = parsedUrl.database || 'admin'; | ||
this.db = this.client.db(dbName); | ||
// there db name from uri ("admin" if no db at uri) | ||
this.db = connectResult; | ||
} | ||
}; | ||
Adapter.prototype.connect = function(callback) { | ||
var self = this; | ||
Adapter.prototype.connect = function connect() { | ||
return Promise.resolve() | ||
.then(() => MongoClient.connect(this.params.url, this.params.options)) | ||
.then((connectResult) => { | ||
this._setDbAndClient(connectResult); | ||
this.collection = this.db.collection('_migrations'); | ||
MongoClient.connect( | ||
self.params.url, | ||
self.params.options || {}, | ||
function(err, dbOrClient) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self._setDbAndClient(dbOrClient); | ||
self.collection = self.db.collection('_migrations'); | ||
callback(null, { | ||
db: self.db, | ||
dropIndexIfExists: self.helpers.dropIndexIfExists | ||
}); | ||
} | ||
); | ||
return { | ||
db: this.db, | ||
dropIndexIfExists: this.helpers.dropIndexIfExists | ||
}; | ||
}); | ||
}; | ||
Adapter.prototype.disconnect = function(callback) { | ||
Adapter.prototype.disconnect = function disconnect() { | ||
if (this.client) { | ||
this.client.close(callback); | ||
return this.client.close(); | ||
} else if (this.db) { | ||
this.db.close(callback); | ||
return this.db.close(); | ||
} else { | ||
callback(); | ||
return Promise.resolve(); | ||
} | ||
}; | ||
Adapter.prototype.getExecutedMigrationNames = function(callback) { | ||
this.collection.find({}).toArray(function(err, docs) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
Adapter.prototype.getExecutedMigrationNames = | ||
function getExecutedMigrationNames() { | ||
return Promise.resolve() | ||
.then(() => this.collection.find({}).toArray()) | ||
.then((docs) => { | ||
return docs.map((doc) => doc._id); | ||
}); | ||
}; | ||
callback(null, docs.map(function(doc) { return doc._id; })); | ||
}); | ||
Adapter.prototype.markExecuted = function markExecuted(name) { | ||
return this.collection.replaceOne({_id: name}, {_id: name}, {upsert: true}); | ||
}; | ||
Adapter.prototype.markExecuted = function(name, callback) { | ||
this.collection.replaceOne({_id: name}, {_id: name}, {upsert: true}, callback); | ||
Adapter.prototype.unmarkExecuted = function unmarkExecuted(name) { | ||
return this.collection.deleteOne({_id: name}); | ||
}; | ||
Adapter.prototype.unmarkExecuted = function(name, callback) { | ||
this.collection.deleteOne({_id: name}, callback); | ||
}; | ||
module.exports = Adapter; |
'use strict'; | ||
exports.dropIndexIfExists = function(collection, index, callback) { | ||
var indexName = ''; | ||
// convert object to string coz `indexExists` don't recognize objects | ||
if (typeof index === 'object') { | ||
for (var key in index) { | ||
indexName += '_' + key + '_' + index[key]; | ||
} | ||
indexName = indexName.replace(/^_/, ''); | ||
} else { | ||
indexName = index; | ||
} | ||
collection.indexExists(indexName, function(err, exist) { | ||
if (err) {callback(err); return;} | ||
if (exist) { | ||
collection.dropIndex(indexName, callback); | ||
} else { | ||
callback(); | ||
} | ||
}); | ||
}; | ||
exports.dropIndexIfExists = | ||
function dropIndexIfExists(collection, index, callback) { | ||
let indexName = ''; | ||
return Promise.resolve() | ||
.then(() => { | ||
// convert object to string coz `indexExists` doesn't` | ||
// recognize objects | ||
if (typeof index === 'object') { | ||
Object.keys(index).forEach((key) => { | ||
indexName += `_${key}_${index[key]}`; | ||
}); | ||
indexName = indexName.replace(/^_/, ''); | ||
} else { | ||
indexName = index; | ||
} | ||
return collection.indexExists(indexName); | ||
}) | ||
.then((indexExist) => { | ||
if (indexExist) { | ||
return collection.dropIndex(indexName); | ||
} | ||
}) | ||
.then(() => { | ||
if (typeof callback === 'function') { | ||
callback(); | ||
} | ||
}); | ||
}; |
(The MIT License) | ||
Copyright (c) 2013-2014 Oleg Korobenko <oleg.korobenko@gmail.com> | ||
Copyright (c) 2013-2019 Oleg Korobenko <oleg.korobenko@gmail.com> | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
{ | ||
"name": "east-mongo", | ||
"description": "mongodb adapter for east (node.js database migration tool)", | ||
"version": "0.3.6", | ||
"version": "1.0.0", | ||
"author": "Oleg Korobenko <oleg.korobenko@gmail.com>", | ||
@@ -11,3 +11,3 @@ "license": "MIT", | ||
}, | ||
"main": "./lib/adapter", | ||
"main": "lib/index.js", | ||
"keywords": [ | ||
@@ -20,2 +20,9 @@ "database", | ||
], | ||
"scripts": { | ||
"test": "tape \"test/**/*.test.js\" | tap_bail | tap-dot", | ||
"testWithoutBail": "tape \"test/**/*.test.js\" | tap-dot", | ||
"makeCodeCoverageSummaryReport": "nyc --reporter text-summary npm test", | ||
"makeCodeCoverageDetailReport": "nyc --reporter=lcov --reporter html npm test", | ||
"lint": "eslint ./" | ||
}, | ||
"peerDependencies": { | ||
@@ -25,7 +32,20 @@ "mongodb": "2.x.x || 3.x.x" | ||
"devDependencies": { | ||
"mongodb": "2.x.x" | ||
"blue-tape": "1.0.0", | ||
"coveralls": "3.0.9", | ||
"es6-promisify": "6.0.2", | ||
"eslint": "4.19.1", | ||
"eslint-config-airbnb-base": "12.1.0", | ||
"eslint-plugin-import": "2.18.2", | ||
"mongodb": "2.x.x || 3.x.x", | ||
"nyc": "14.1.1", | ||
"tap-dot": "2.0.0", | ||
"tap_bail": "1.0.1", | ||
"tape": "4.11.0", | ||
"tape-catch": "1.0.6", | ||
"tape-promise": "4.0.0" | ||
}, | ||
"dependencies": { | ||
"mongodb-uri": "0.9.7" | ||
"dependencies": {}, | ||
"engines": { | ||
"node": ">=4.0.0" | ||
} | ||
} |
164
README.md
@@ -6,2 +6,6 @@ # east mongo | ||
*Please note* that mainstream mongodb adapter version (>= 1.x) requires | ||
east >= 1.x, for using adapter with older east versions (prior to 1.x) please | ||
use mongodb adapter version < 1.x. | ||
All executed migrations names will be stored at `_migrations` collection in the | ||
@@ -11,28 +15,53 @@ current database. Object with following properties will be passed to `migrate` | ||
* `db` - instance of [mongodb native db](http://mongodb.github.io/node-mongodb-native/api-generated/db.html) | ||
* `dropIndexIfExists` function(collection, index, callback) - helper function | ||
* `db` - instance of [mongodb native db](http://mongodb.github.io/node-mongodb-native/3.4/api/Db.html) | ||
* `dropIndexIfExists` function(collection, index, [callback]) - helper function | ||
which can be used for dropping index in safe way (contrasting to | ||
`collection.dropIndex` which throws an error if index doesn't exist). | ||
`collection.dropIndex` which throws an error if index doesn't exist). This | ||
function returns promise and can be used that way instead of providing | ||
callback. | ||
east mongo package also provides following migration templates: | ||
* [lib/migrationTemplates/promises.js](lib/migrationTemplates/promises.js) - | ||
default migration template, uses built-in `Promise` in `migrate`, | ||
`rollback` functions. | ||
* [lib/migrationTemplates/async.js](lib/migrationTemplates/async.js) - | ||
migration template that uses async functions to describe `migrate`, | ||
`rollback` functions. | ||
## Installation | ||
Default migration template will be used if `template` is not set. To get path | ||
of another template `require.resolve` could be used, e.g. at `.eastrc`: | ||
```sh | ||
npm install east east-mongo -g | ||
```js | ||
module.exports = { | ||
template: require.resolve('east-mongo/lib/migrationTemplates/async.js') | ||
} | ||
``` | ||
alternatively you could install it locally | ||
[](https://www.npmjs.org/package/east-mongo) | ||
[](https://travis-ci.org/okv/east-mongo) | ||
[](https://coveralls.io/github/okv/east-mongo?branch=master) | ||
[](https://snyk.io/test/npm/east-mongo) | ||
## Usage | ||
## Node.js compatibility | ||
go to project dir and run | ||
east mongo requires node.js >= 4 to work. | ||
## Installation | ||
mongodb adapter requires `mongodb` package as peer dependency (versions 2.x and | ||
3.x are supported), so you should install it manually along side with east: | ||
```sh | ||
east init | ||
npm install east east-mongo mongodb@3 | ||
``` | ||
create `.eastrc` file at current directory | ||
alternatively you could install it globally | ||
## Usage | ||
Sample `.eastrc` content: | ||
```js | ||
@@ -53,115 +82,28 @@ { | ||
where `url` is url of database which you want to migrate (in | ||
[mongodb native url connection format](http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html#the-url-connection-format)) and `options` is optional settings (see [connect method specification](http://mongodb.github.io/node-mongodb-native/2.0/api/MongoClient.html#connect)). | ||
[mongodb native url connection format](http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html#the-url-connection-format)) and `options` is optional settings | ||
(see [connect method specification](http://mongodb.github.io/node-mongodb-native/3.4/api/MongoClient.html#.connect)). | ||
now we can create some migrations | ||
Migration files created with default `template` that comes with adapter will | ||
look like: | ||
```sh | ||
east create apples | ||
east create bananas | ||
``` | ||
created files will looks like this one | ||
```js | ||
exports.migrate = function(client, done) { | ||
var db = client.db; | ||
done(); | ||
}; | ||
exports.tags = []; | ||
exports.rollback = function(client, done) { | ||
var db = client.db; | ||
done(); | ||
}; | ||
``` | ||
exports.migrate = function(params) { | ||
const db = params.db; | ||
edit created files and insert | ||
to 1_apples | ||
```js | ||
exports.migrate = function(client, done) { | ||
var db = client.db; | ||
db.collection('things').insert({_id: 1, name: 'apple', color: 'red'}, function(err) { | ||
if (err) done(err); | ||
db.collection('things').insert({_id: 2, name: 'apple', color: 'green'}, done); | ||
}); | ||
return Promise.resolve(); | ||
}; | ||
exports.rollback = function(client, done) { | ||
var db = client.db; | ||
db.collection('things').remove({_id: {$in: [1, 2]}}, done); | ||
}; | ||
``` | ||
exports.rollback = function(params) { | ||
const db = params.db; | ||
to 2_bananas | ||
```js | ||
exports.migrate = function(client, done) { | ||
var db = client.db; | ||
db.collection('things').insert({_id: 3, name: 'banana', color: 'yellow'}, done); | ||
return Promise.resolve(); | ||
}; | ||
exports.rollback = function(client, done) { | ||
var db = client.db; | ||
db.collection('things').remove({_id: 3}, done); | ||
}; | ||
``` | ||
now we can execute our migrations | ||
See east [cli](https://github.com/okv/east#cli-usage) or | ||
[library](https://github.com/okv/east#library-usage) usage for more details. | ||
```sh | ||
east migrate | ||
``` | ||
output | ||
```sh | ||
target migrations: | ||
1_apples | ||
2_bananas | ||
migrate `1_apples` | ||
migration done | ||
migrate `2_bananas` | ||
migration done | ||
``` | ||
and roll them back | ||
```sh | ||
east rollback | ||
``` | ||
output | ||
```sh | ||
target migrations: | ||
2_bananas | ||
1_apples | ||
rollback `2_bananas` | ||
migration successfully rolled back | ||
rollback `1_apples` | ||
migration successfully rolled back | ||
``` | ||
you can specify one or several particular migrations for migrate/rollback e.g. | ||
```sh | ||
east migrate 1_apples | ||
``` | ||
or | ||
```sh | ||
east migrate 1_apples 2_bananas | ||
``` | ||
Run `east -h` to see all commands, `east <command> -h` to see detail command help, | ||
see also [east page](https://github.com/okv/east#usage) for command examples. | ||
## Running test | ||
run [east](https://github.com/okv/east#running-test) tests with this adapter | ||
## License | ||
@@ -168,0 +110,0 @@ |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
9107
1
8
111
1
13
110
- Removedmongodb-uri@0.9.7
- Removedmongodb-uri@0.9.7(transitive)