First typescript iteration
[oweals/peertube.git] / server / initializers / migrator.ts
1 import { waterfall, eachSeries } from 'async'
2 import fs = require('fs')
3 import path = require('path')
4
5 const db = require('./database')
6 import { LAST_MIGRATION_VERSION } from './constants'
7 import { logger } from '../helpers'
8
9 function migrate (finalCallback) {
10   waterfall([
11
12     function checkApplicationTableExists (callback) {
13       db.sequelize.getQueryInterface().showAllTables().asCallback(function (err, tables) {
14         if (err) return callback(err)
15
16         // No tables, we don't need to migrate anything
17         // The installer will do that
18         if (tables.length === 0) return finalCallback(null)
19
20         return callback(null)
21       })
22     },
23
24     function loadMigrationVersion (callback) {
25       db.Application.loadMigrationVersion(callback)
26     },
27
28     function createMigrationRowIfNotExists (actualVersion, callback) {
29       if (actualVersion === null) {
30         db.Application.create({
31           migrationVersion: 0
32         }, function (err) {
33           return callback(err, 0)
34         })
35       }
36
37       return callback(null, actualVersion)
38     },
39
40     function abortMigrationIfNotNeeded (actualVersion, callback) {
41       // No need migrations
42       if (actualVersion >= LAST_MIGRATION_VERSION) return finalCallback(null)
43
44       return callback(null, actualVersion)
45     },
46
47     function getMigrations (actualVersion, callback) {
48       // If there are a new migration scripts
49       logger.info('Begin migrations.')
50
51       getMigrationScripts(function (err, migrationScripts) {
52         return callback(err, actualVersion, migrationScripts)
53       })
54     },
55
56     function doMigrations (actualVersion, migrationScripts, callback) {
57       eachSeries(migrationScripts, function (entity, callbackEach) {
58         executeMigration(actualVersion, entity, callbackEach)
59       }, function (err) {
60         if (err) return callback(err)
61
62         logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION)
63         return callback(null)
64       })
65     }
66   ], finalCallback)
67 }
68
69 // ---------------------------------------------------------------------------
70
71 export {
72   migrate
73 }
74
75 // ---------------------------------------------------------------------------
76
77 function getMigrationScripts (callback) {
78   fs.readdir(path.join(__dirname, 'migrations'), function (err, files) {
79     if (err) return callback(err)
80
81     const filesToMigrate = []
82
83     files.forEach(function (file) {
84       // Filename is something like 'version-blabla.js'
85       const version = file.split('-')[0]
86       filesToMigrate.push({
87         version,
88         script: file
89       })
90     })
91
92     return callback(err, filesToMigrate)
93   })
94 }
95
96 function executeMigration (actualVersion, entity, callback) {
97   const versionScript = parseInt(entity.version)
98
99   // Do not execute old migration scripts
100   if (versionScript <= actualVersion) return callback(null)
101
102   // Load the migration module and run it
103   const migrationScriptName = entity.script
104   logger.info('Executing %s migration script.', migrationScriptName)
105
106   const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName))
107
108   db.sequelize.transaction().asCallback(function (err, t) {
109     if (err) return callback(err)
110
111     const options = {
112       transaction: t,
113       queryInterface: db.sequelize.getQueryInterface(),
114       sequelize: db.sequelize,
115       Sequelize: db.Sequelize
116     }
117     migrationScript.up(options, function (err) {
118       if (err) {
119         t.rollback()
120         return callback(err)
121       }
122
123       // Update the new migration version
124       db.Application.updateMigrationVersion(versionScript, t, function (err) {
125         if (err) {
126           t.rollback()
127           return callback(err)
128         }
129
130         t.commit().asCallback(callback)
131       })
132     })
133   })
134 }