1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.migrate = exports.readMigrations = void 0;
|
4 | const fs = require("fs");
|
5 | const path = require("path");
|
6 | async function readMigrations(migrationPath) {
|
7 | const migrationsPath = migrationPath || path.join(process.cwd(), 'migrations');
|
8 | const location = path.resolve(migrationsPath);
|
9 |
|
10 |
|
11 |
|
12 | const migrationFiles = await new Promise((resolve, reject) => {
|
13 | fs.readdir(location, (err, files) => {
|
14 | if (err) {
|
15 | return reject(err);
|
16 | }
|
17 | resolve(files
|
18 | .map(x => x.match(/^(\d+).(.*?)\.sql$/))
|
19 | .filter(x => x !== null)
|
20 | .map(x => ({ id: Number(x[1]), name: x[2], filename: x[0] }))
|
21 | .sort((a, b) => Math.sign(a.id - b.id)));
|
22 | });
|
23 | });
|
24 | if (!migrationFiles.length) {
|
25 | throw new Error(`No migration files found in '${location}'.`);
|
26 | }
|
27 |
|
28 |
|
29 |
|
30 | return Promise.all(migrationFiles.map(migration => new Promise((resolve, reject) => {
|
31 | const filename = path.join(location, migration.filename);
|
32 | fs.readFile(filename, 'utf-8', (err, data) => {
|
33 | if (err) {
|
34 | return reject(err);
|
35 | }
|
36 | const [up, down] = data.split(/^--\s+?down\b/im);
|
37 | const migrationData = migration;
|
38 | migrationData.up = up.replace(/^-- .*?$/gm, '').trim();
|
39 | migrationData.down = down ? down.trim() : '';
|
40 | resolve(migrationData);
|
41 | });
|
42 | })));
|
43 | }
|
44 | exports.readMigrations = readMigrations;
|
45 |
|
46 |
|
47 |
|
48 | async function migrate(db, config = {}) {
|
49 | config.force = config.force || false;
|
50 | config.table = config.table || 'migrations';
|
51 | const { force, table } = config;
|
52 | const migrations = config.migrations
|
53 | ? config.migrations
|
54 | : await readMigrations(config.migrationsPath);
|
55 |
|
56 | await db.run(`CREATE TABLE IF NOT EXISTS "${table}" (
|
57 | id INTEGER PRIMARY KEY,
|
58 | name TEXT NOT NULL,
|
59 | up TEXT NOT NULL,
|
60 | down TEXT NOT NULL
|
61 | )`);
|
62 |
|
63 | let dbMigrations = await db.all(`SELECT id, name, up, down FROM "${table}" ORDER BY id ASC`);
|
64 |
|
65 |
|
66 | const lastMigration = migrations[migrations.length - 1];
|
67 | for (const migration of dbMigrations
|
68 | .slice()
|
69 | .sort((a, b) => Math.sign(b.id - a.id))) {
|
70 | if (!migrations.some(x => x.id === migration.id) ||
|
71 | (force && migration.id === lastMigration.id)) {
|
72 | await db.run('BEGIN');
|
73 | try {
|
74 | await db.exec(migration.down);
|
75 | await db.run(`DELETE FROM "${table}" WHERE id = ?`, migration.id);
|
76 | await db.run('COMMIT');
|
77 | dbMigrations = dbMigrations.filter(x => x.id !== migration.id);
|
78 | }
|
79 | catch (err) {
|
80 | await db.run('ROLLBACK');
|
81 | throw err;
|
82 | }
|
83 | }
|
84 | else {
|
85 | break;
|
86 | }
|
87 | }
|
88 |
|
89 | const lastMigrationId = dbMigrations.length
|
90 | ? dbMigrations[dbMigrations.length - 1].id
|
91 | : 0;
|
92 | for (const migration of migrations) {
|
93 | if (migration.id > lastMigrationId) {
|
94 | await db.run('BEGIN');
|
95 | try {
|
96 | await db.exec(migration.up);
|
97 | await db.run(`INSERT INTO "${table}" (id, name, up, down) VALUES (?, ?, ?, ?)`, migration.id, migration.name, migration.up, migration.down);
|
98 | await db.run('COMMIT');
|
99 | }
|
100 | catch (err) {
|
101 | await db.run('ROLLBACK');
|
102 | throw err;
|
103 | }
|
104 | }
|
105 | }
|
106 | }
|
107 | exports.migrate = migrate;
|
108 |
|
\ | No newline at end of file |