Use async/await in lib and initializers
[oweals/peertube.git] / server / initializers / migrator.ts
1 import * as path from 'path'
2
3 import { database as db } from './database'
4 import { LAST_MIGRATION_VERSION } from './constants'
5 import { logger, readdirPromise } from '../helpers'
6
7 async function migrate () {
8   const tables = await db.sequelize.getQueryInterface().showAllTables()
9
10   // No tables, we don't need to migrate anything
11   // The installer will do that
12   if (tables.length === 0) return
13
14   let actualVersion = await db.Application.loadMigrationVersion()
15   if (actualVersion === null) {
16     await db.Application.create({ migrationVersion: 0 })
17     actualVersion = 0
18   }
19
20   // No need migrations, abort
21   if (actualVersion >= LAST_MIGRATION_VERSION) return
22
23   // If there are a new migration scripts
24   logger.info('Begin migrations.')
25
26   const migrationScripts = await getMigrationScripts()
27
28   for (const migrationScript of migrationScripts) {
29     await executeMigration(actualVersion, migrationScript)
30   }
31
32   logger.info('Migrations finished. New migration version schema: %s', LAST_MIGRATION_VERSION)
33 }
34
35 // ---------------------------------------------------------------------------
36
37 export {
38   migrate
39 }
40
41 // ---------------------------------------------------------------------------
42
43 async function getMigrationScripts () {
44   const files = await readdirPromise(path.join(__dirname, 'migrations'))
45   const filesToMigrate: {
46     version: string,
47     script: string
48   }[] = []
49
50   files
51     .filter(file => file.endsWith('.js.map') === false)
52     .forEach(file => {
53       // Filename is something like 'version-blabla.js'
54       const version = file.split('-')[0]
55       filesToMigrate.push({
56         version,
57         script: file
58       })
59     })
60
61   return filesToMigrate
62 }
63
64 async function executeMigration (actualVersion: number, entity: { version: string, script: string }) {
65   const versionScript = parseInt(entity.version, 10)
66
67   // Do not execute old migration scripts
68   if (versionScript <= actualVersion) return undefined
69
70   // Load the migration module and run it
71   const migrationScriptName = entity.script
72   logger.info('Executing %s migration script.', migrationScriptName)
73
74   const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName))
75
76   await db.sequelize.transaction(async t => {
77     const options = {
78       transaction: t,
79       queryInterface: db.sequelize.getQueryInterface(),
80       sequelize: db.sequelize,
81       db
82     }
83
84     await migrationScript.up(options)
85
86     // Update the new migration version
87     await db.Application.updateMigrationVersion(versionScript, t)
88   })
89 }