-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #99 from ELEVATE-Project/migrations
Migrations
- Loading branch information
Showing
16 changed files
with
557 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{ "mongoUri": "mongodb://127.0.0.1:54466/", "mongoDBName": "jest" } | ||
{ "mongoUri": "mongodb://127.0.0.1:59200/", "mongoDBName": "jest" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
const endpoints = require('../constants/endpoints') | ||
const request = require('request') | ||
module.exports = { | ||
async up(db) { | ||
global.migrationMsg = 'Session Form Created' | ||
|
||
const form = await db.collection('forms').findOne({ type: 'session' }) | ||
if (!form) { | ||
const categories = await db | ||
.collection('entities') | ||
.find( | ||
{ type: 'categories', status: 'ACTIVE', deleted: false }, | ||
{ projection: { value: 1, label: 1, image: 1, _id: 0 } } | ||
) | ||
.toArray() | ||
|
||
const controls = [ | ||
{ | ||
name: 'title', | ||
label: 'Session Title', | ||
type: 'text', | ||
position: 'floating', | ||
}, | ||
{ | ||
name: 'description', | ||
label: 'Description', | ||
type: 'textarea', | ||
position: 'floating', | ||
}, | ||
{ | ||
name: 'startDate', | ||
label: 'Start Date', | ||
displayFormat: 'DD/MMM/YYYY HH:mm', | ||
dependedChild: 'endDate', | ||
type: 'date', | ||
position: 'floating', | ||
}, | ||
{ | ||
name: 'endDate', | ||
label: 'End Date', | ||
displayFormat: 'DD/MMM/YYYY HH:mm', | ||
type: 'date', | ||
position: 'floating', | ||
}, | ||
{ | ||
name: 'recommendedFor', | ||
label: 'Recommended For', | ||
type: 'chip', | ||
disabled: false, | ||
showSelectAll: true, | ||
showAddOption: true, | ||
optionsUrl: { url: 'roles/search', method: 'POST' }, | ||
options: [ | ||
{ value: 'deo', label: 'District education officer' }, | ||
{ value: 'beo', label: 'Block education officer' }, | ||
{ value: 'hm', label: 'Head Master' }, | ||
{ value: 'TE', label: 'Teacher' }, | ||
{ value: 'CO', label: 'Cluster Officials' }, | ||
], | ||
}, | ||
{ | ||
name: 'categories', | ||
label: 'Categories', | ||
type: 'chip', | ||
disabled: false, | ||
showSelectAll: true, | ||
showAddOption: true, | ||
options: categories, | ||
}, | ||
{ | ||
name: 'medium', | ||
label: 'Select Medium', | ||
type: 'chip', | ||
disabled: false, | ||
showSelectAll: true, | ||
showAddOption: true, | ||
options: [ | ||
{ label: 'English', value: '1' }, | ||
{ label: 'Hindi', value: '2' }, | ||
], | ||
}, | ||
] | ||
const nullPosition = ['medium', 'categories', 'recommendedFor'] | ||
controls.forEach((element) => { | ||
if (nullPosition.includes(element.name)) { | ||
element.position = '' | ||
} else { | ||
element.position = 'floating' | ||
} | ||
element.validators = { required: true } | ||
element.class = 'ion-margin' | ||
element.value = '' | ||
}) | ||
|
||
let formsData = { | ||
type: 'session', | ||
subType: 'sessionForm', | ||
action: 'sessionFields', | ||
ver: '1.0', | ||
data: { | ||
templateName: 'defaultTemplate', | ||
fields: { | ||
controls: controls, | ||
}, | ||
}, | ||
} | ||
await db.collection('forms').insertOne(formsData) | ||
} | ||
}, | ||
|
||
async down(db) { | ||
const form = await db.collection('forms').findOne({ type: 'session' }) | ||
if (form) { | ||
await db.collection('forms').deleteOne({ type: 'session' }) | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Mentoring Service | ||
|
||
## Check migrations | ||
|
||
npm run elevate-migrations s | ||
|
||
## Create migrations | ||
|
||
npm run elevate-migrations create <migration-name> | ||
|
||
## Run migrations | ||
|
||
npm run elevate-migrations up | ||
|
||
## Down migrations | ||
|
||
npm run elevate-migrations down |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#! /usr/bin/env node | ||
|
||
const program = require('commander') | ||
global._ = require('lodash') | ||
const Table = require('cli-table') | ||
const migrateMongo = require('../lib/migrate') | ||
const pkgjson = require('../../../package.json') | ||
|
||
function printMigrated(migrated = []) { | ||
migrated.forEach((migratedItem) => { | ||
console.log(`MIGRATED UP: ${migratedItem}`) | ||
}) | ||
} | ||
|
||
function handleError(err) { | ||
console.error(`ERROR: ${err.message}`) | ||
process.exit(1) | ||
} | ||
|
||
function printStatusTable(statusItems) { | ||
const table = new Table({ head: ['Filename', 'Applied At'] }) | ||
statusItems.forEach((item) => table.push(_.values(item))) | ||
console.log(table.toString()) | ||
} | ||
|
||
program.version(pkgjson.version) | ||
|
||
program | ||
.command('initialization') | ||
.alias('i') | ||
.description('initialize a new migration project') | ||
.action(() => | ||
migrateMongo | ||
.init() | ||
.then(() => console.log(`Initialization successful. Please edit the generated file`)) | ||
.catch((err) => handleError(err)) | ||
) | ||
|
||
program | ||
.command('create [description]') | ||
.alias('c') | ||
.description('create a new database migration with the provided description') | ||
.option('-f --file <file>', 'use a custom config file') | ||
.action((description, options) => { | ||
global.options = options | ||
migrateMongo | ||
.create(description) | ||
.then((fileName) => console.log(`Created: ${fileName}`)) | ||
.catch((err) => handleError(err)) | ||
}) | ||
|
||
program | ||
.command('up') | ||
.alias('u') | ||
.description('run all pending database migrations') | ||
.option('-n --name <name>', 'use a custom config name') | ||
.action((env, options) => { | ||
global.alias = env._alias | ||
if (env.name !== '') { | ||
global.upgradeOneItem = env.name | ||
} | ||
global.options = options | ||
migrateMongo.database | ||
.connect() | ||
.then((db) => migrateMongo.up(db)) | ||
.then((migrated) => { | ||
printMigrated(migrated) | ||
process.exit(0) | ||
}) | ||
.catch((err) => { | ||
handleError(err) | ||
printMigrated(err.migrated) | ||
}) | ||
}) | ||
|
||
program | ||
.command('down') | ||
.alias('d') | ||
.description('undo the last applied database migration') | ||
.option('-n --name <name>', 'use a custom config name') | ||
.action((env, options) => { | ||
global.alias = env._alias | ||
if (env.name !== '') { | ||
global.downgradeOneItem = env.name | ||
} | ||
global.options = options | ||
migrateMongo.database | ||
.connect() | ||
.then((db) => migrateMongo.down(db)) | ||
.then((migrated) => { | ||
migrated.forEach((migratedItem) => { | ||
console.log(`MIGRATED DOWN: ${migratedItem}`) | ||
}) | ||
process.exit(0) | ||
}) | ||
.catch((err) => { | ||
handleError(err) | ||
}) | ||
}) | ||
|
||
program | ||
.command('status') | ||
.alias('s') | ||
.description('print the changelog of the database') | ||
.option('-f --file <file>', 'use a custom config file') | ||
.action((env, options) => { | ||
global.alias = env._alias | ||
global.options = options | ||
migrateMongo.database | ||
.connect() | ||
.then((db) => migrateMongo.status(db)) | ||
.then((statusItems) => { | ||
printStatusTable(statusItems) | ||
process.exit(0) | ||
}) | ||
.catch((err) => { | ||
handleError(err) | ||
}) | ||
}) | ||
|
||
program.parse(process.argv) | ||
|
||
if (_.isEmpty(program.args)) { | ||
program.outputHelp() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const fs = require('fs-extra') | ||
const path = require('path') | ||
const moment = require('moment-timezone') | ||
const migrationsDir = require('../env/migrationsDir') | ||
|
||
module.exports = async (description) => { | ||
if (!description) { | ||
throw new Error('Missing parameter: description') | ||
} | ||
await migrationsDir.shouldExist() | ||
const source = path.join(__dirname, '../../samples/migration.js') | ||
const filename = `${moment().format('YYYYMMDDHHmmss')}-${description.split(' ').join('_')}.js` | ||
const destination = path.join(await migrationsDir.resolve(), filename) | ||
await fs.copy(source, destination) | ||
return filename | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
const _ = require('lodash') | ||
const fnArgs = require('fn-args') | ||
const { promisify } = require('util') | ||
const status = require('./status') | ||
const migrationsDir = require('../env/migrationsDir') | ||
|
||
module.exports = async (db) => { | ||
const downgraded = [] | ||
const statusItems = await status(db) | ||
const appliedItems = statusItems.filter((item) => item.appliedAt !== 'PENDING') | ||
const lastAppliedItem = _.last(appliedItems) | ||
|
||
if (lastAppliedItem) { | ||
try { | ||
const migration = await migrationsDir.loadMigration(lastAppliedItem.fileName) | ||
const args = fnArgs(migration.down) | ||
const down = args.length > 1 ? promisify(migration.down) : migration.down | ||
await down(db) | ||
} catch (err) { | ||
throw new Error(`Could not migrate down ${lastAppliedItem.fileName}: ${err.message}`) | ||
} | ||
|
||
const collectionName = process.env.MIGRATION_COLLECTION || 'migrations' | ||
const collection = db.collection(collectionName) | ||
try { | ||
await collection.deleteOne({ fileName: lastAppliedItem.fileName }) | ||
downgraded.push(lastAppliedItem.fileName) | ||
} catch (err) { | ||
throw new Error(`Could not update changelog: ${err.message}`) | ||
} | ||
} | ||
|
||
return downgraded | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const fs = require('fs-extra') | ||
const path = require('path') | ||
|
||
const migrationsDir = require('../env/migrationsDir') | ||
|
||
function createMigrationsDirectory() { | ||
return fs.mkdirs(path.join(process.cwd(), process.env.MIGRATION_DIR)) | ||
} | ||
|
||
module.exports = async () => { | ||
await migrationsDir.shouldNotExist() | ||
return createMigrationsDirectory() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const { find } = require('lodash') | ||
const migrationsDir = require('../env/migrationsDir') | ||
|
||
module.exports = async (db) => { | ||
await migrationsDir.shouldExist() | ||
|
||
let fileValue | ||
const fileNames = await migrationsDir.getFileNames() | ||
|
||
if (alias == 'u' && upgradeOneItem && fileNames.includes(upgradeOneItem)) { | ||
fileValue = [upgradeOneItem] | ||
} else if (alias == 'd' && downgradeOneItem && fileNames.includes(downgradeOneItem)) { | ||
fileValue = [downgradeOneItem] | ||
} else { | ||
fileValue = fileNames | ||
} | ||
const collectionName = process.env.MIGRATION_COLLECTION || 'migrations' | ||
|
||
const collection = db.collection(collectionName) | ||
const changelog = await collection.find({}).toArray() | ||
|
||
const statusTable = fileValue.map((fileName) => { | ||
const itemInLog = find(changelog, { fileName }) | ||
const appliedAt = itemInLog ? itemInLog.appliedAt.toJSON() : 'PENDING' | ||
return { fileName, appliedAt } | ||
}) | ||
|
||
return statusTable | ||
} |
Oops, something went wrong.