setup.js 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. const _ = require('lodash')
  2. const sequelize = require('./sequelize')
  3. const Sequelize = require('sequelize')
  4. const migrations = require('./migrations')
  5. const chalk = require('chalk')
  6. const Version = sequelize.define('_version', {
  7. key: {
  8. type: Sequelize.STRING,
  9. primaryKey: true
  10. },
  11. value: Sequelize.DOUBLE
  12. }, {
  13. tableName: '_version',
  14. timestamps: false
  15. })
  16. const getVersion = async (namespace, queryInterface) => {
  17. const defaultVersion = migrations[namespace].defaultVersion || migrations[namespace].map(x => x.version).reduce((a, b) => Math.max(a, b), 0.0)
  18. const tables = await queryInterface.showAllTables()
  19. if (!tables.includes('_version')) {
  20. return defaultVersion
  21. } else {
  22. const result = await Version.findOne({where: {key: namespace}})
  23. if (result) {
  24. return result.value
  25. } else {
  26. return defaultVersion
  27. }
  28. }
  29. }
  30. const setVersion = async (namespace, version, queryInterface) => {
  31. await Version.upsert({key: namespace, value: version}, { where: { key: namespace }})
  32. }
  33. const migrate = async (namespace, targetVersion) => {
  34. const queryInterface = sequelize.getQueryInterface()
  35. const currentVersion = await getVersion(namespace, queryInterface)
  36. let migs = _.sortBy(migrations[namespace], 'version')
  37. if (!targetVersion) targetVersion = migs.map(x => x.version).reduce((a, b) => Math.max(a, b), 0)
  38. console.log(chalk.green(`Migrating ${namespace}`))
  39. console.log(chalk.yellow(`Current version: ${currentVersion}`))
  40. console.log(chalk.yellow(`Target version: ${targetVersion}`))
  41. // Sanity check
  42. for (let mig of migs) {
  43. if (!mig.version) throw new Error(`All migrations require versions`)
  44. if (!mig.up) throw new Error('All migrations require `up`')
  45. }
  46. // Filter to relevant migrations
  47. migs = migs.filter(mig => mig.version > currentVersion && mig.version <= targetVersion)
  48. console.log(`Migrations to run: ${migs.map(x => x.version).join(', ')}`)
  49. let lastVersion = currentVersion
  50. for (let mig of migs) {
  51. if (mig.version > lastVersion) {
  52. console.log(chalk.blue(`Running migration ${mig.version}: ${mig.name}`))
  53. mig.description && console.log(chalk.blue(mig.description))
  54. let newVersion = await mig.up(queryInterface, Sequelize)
  55. if (!Number.isFinite(newVersion)) throw new Error(`All migrations must return the resulting version`)
  56. if (newVersion < lastVersion) throw new Error(`Up migration downgraded database: ${mig.version} -> ${newVersion}`)
  57. await setVersion(namespace, newVersion, queryInterface)
  58. console.log(`Database now at version ${newVersion}`)
  59. lastVersion = newVersion
  60. } else {
  61. console.log(chalk.blue(`Skipping migration ${mig.version}: ${mig.name}`))
  62. }
  63. }
  64. console.log(chalk.cyan(`Migration complete. Current database version: ${await getVersion(namespace, queryInterface)}`))
  65. }
  66. const migrateAll = async () => {
  67. const namespaces = _.keys(_.omit(migrations, 'material-framework'))
  68. await migrate('material-framework')
  69. console.log(_.keys(migrations))
  70. for (let namespace of namespaces) {
  71. await migrate(namespace)
  72. }
  73. }
  74. module.exports = {
  75. getVersion,
  76. migrate,
  77. migrateAll,
  78. migrations,
  79. setVersion
  80. }