-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsequence.js
90 lines (75 loc) · 3.02 KB
/
sequence.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import Promise from "bluebird";
import Migration from "./migration";
import Program from "./program";
export default class Sequence {
static readMigrations(fs, dirPath, first = 1, last) {
return Promise.fromCallback(cb => fs.readdir(dirPath, cb))
.then(files => {
const migrations = [];
let prologue;
let epilogue;
for (let ea of files) {
if (ea === "prologue.sql") {
prologue = Program.fromFile(fs, dirPath, ea);
} else if (ea === "epilogue.sql") {
epilogue = Program.fromFile(fs, dirPath, ea);
} else if (/^\d+-[^.]+.sql/.test(ea)) {
migrations.push(Migration.fromFile(fs, dirPath, ea));
}
}
return Promise.all([prologue, Promise.all(migrations), epilogue]);
})
.spread((prologue, migrations, epilogue) => {
migrations.sort((a, b) => a.ordinal - b.ordinal);
let lim = migrations.length;
for (let i = 0; i < lim; i++) {
const expected = i + 1;
if (migrations[i].ordinal < expected) {
throw new Error(`Duplicate migration number ${migrations[i].ordinal}`);
}
if (migrations[i].ordinal > expected) {
throw new Error(`Missing migration number ${migrations[i].ordinal}`);
}
}
migrations = migrations.filter(ea => ea.ordinal >= first);
if (last !== undefined) {
migrations = migrations.filter(ea => ea.ordinal <= last);
}
if (prologue) {
migrations.unshift(prologue);
}
if (epilogue) {
migrations.push(epilogue);
}
return new this(...migrations);
});
}
static async getLatestMigration(fs, dirPath) {
const sequence = await this.readMigrations(fs, dirPath);
for (let i = sequence.programs.length - 1; i >= 0; i--) {
if (sequence.programs[i] && sequence.programs[i].ordinal) {
return sequence.programs[i].ordinal;
}
}
return null;
}
constructor() {
this.programs = [...arguments];
}
checkContext(context) {
this.programs.forEach(ea => ea.checkContext(context));
}
exec(client, context, options) {
let vow = Promise.resolve();
this.programs.forEach(ea => {
vow = vow.then(() => ea.exec(client, context, options));
});
return vow;
}
execInTransaction(client, context, options) {
return client
.exec("BEGIN")
.then(() => this.exec(client, context, options))
.then(result => client.exec("COMMIT").return(result), err => client.exec("ROLLBACK").throw(err));
}
}