1 | const crypto = require('crypto')
|
2 | const fs = require('./utils/fs')
|
3 | const path = require('path')
|
4 | const { getConfig } = require('./config')
|
5 | const { listDirectoryFiles } = require('./utils/fs')
|
6 |
|
7 | exports.getSampleMigration = async () => {
|
8 | return fs.readFile(path.resolve(__dirname, './templates/migration.js'), 'utf8')
|
9 | }
|
10 |
|
11 | exports.getPendingJobs = async () => {
|
12 | const config = await getConfig()
|
13 | const context = await config.context()
|
14 | const state = await config.fetchState(context)
|
15 | const alreadyRanFiles = state.history.map(({ filename }) => filename)
|
16 |
|
17 |
|
18 | const roundId = crypto.randomBytes(20).toString('hex')
|
19 |
|
20 |
|
21 |
|
22 | const files = await listDirectoryFiles(config.migrationsDirectory)
|
23 |
|
24 | const pendingMigrations = files
|
25 | .filter((filename) => {
|
26 | if (!filename.endsWith('.js')) return false
|
27 | return !alreadyRanFiles.includes(filename)
|
28 | })
|
29 | .sort()
|
30 | .map((filename) => ({
|
31 | roundId,
|
32 | filename,
|
33 | path: path.join(config.migrationsDirectory, filename),
|
34 | }))
|
35 |
|
36 | return pendingMigrations
|
37 | }
|
38 |
|
39 | exports.runPendingMigrations = async () => {
|
40 | const config = await getConfig()
|
41 |
|
42 | const pendingMigrations = await this.getPendingJobs()
|
43 |
|
44 | if (pendingMigrations.length) {
|
45 | if (config.beforeAll) await config.beforeAll(pendingMigrations)
|
46 |
|
47 | for (const migrationJob of pendingMigrations) {
|
48 | await this.up(migrationJob)
|
49 | }
|
50 | if (config.afterAll) await config.afterAll(pendingMigrations)
|
51 | }
|
52 |
|
53 | return pendingMigrations
|
54 | }
|
55 |
|
56 | exports.up = async (migrationJob) => {
|
57 | const config = await getConfig()
|
58 | const context = await config.context()
|
59 | const state = await config.fetchState(context)
|
60 |
|
61 |
|
62 | migrationJob.startedAt = (new Date()).toJSON()
|
63 | await config.beforeEach(migrationJob)
|
64 |
|
65 |
|
66 | const migrationModule = require(migrationJob.path)
|
67 | await migrationModule.up(context)
|
68 |
|
69 |
|
70 | migrationJob.finishedAt = (new Date()).toJSON()
|
71 | await config.afterEach(migrationJob)
|
72 |
|
73 |
|
74 |
|
75 | delete migrationJob.path
|
76 | state.history.push(migrationJob)
|
77 | state.lastRan = migrationJob.finishedAt
|
78 | await config.storeState(state, context)
|
79 |
|
80 | return state
|
81 | }
|