-
Notifications
You must be signed in to change notification settings - Fork 227
Description
Because 90% of all use cases involve SQL, or at least that's my suspicion, when using a migration tool like this package provides. That's why I think it might be good addition to include an utility function what adds support for doing something based on a list of (SQL) files their content.
Currently I'm using a function in one of my projects just like that and I thought why not share it?
...
All what is needed is a file structure like this (note as of v1.7.0, you can't have this structure in the same directory as where your migrations are stored, it should be on a higher level):
.
├── up
│ ├── 00-tables.sql
│ └── 123-triggers.sql
└── down
├── 00-tables.sql
└── 123-triggers.sql
Then the next thing to do is to setup a single migration:
const {upFromFiles, downFromFiles} = require("migrate"); // Not available yet?
const database = require("./database");
const upHandler = async (fileContents) => {
// Do something with the contents of the file.
// This example is querying the database
const pool = database.getPool(); // Setup a database connection
await pool.query(fileContents); // Send a query to the database
};
// This function is needed if you maintain the same order in the down SQL files as you do in the up files.
// Example:
// - up file: create table posts (...); create table comments (..., post_id int references posts);
// - down file: drop table posts; drop table comments;
// This function reverses the order of those statements: drop table comments; drop table posts;
const downHandler = async (fileContents) => {
const seperator = ";";
const reversedContents = fileContents
.split(seperator)
.reverse()
.join(seperator);
await upHandler(reversedContents);
};
module.exports.up = async () => {
await upFromFiles("./up", upHandler);
};
module.exports.down = async () => {
await downFromFiles("./down", downHandler);
};
The functions upFromFiles
and downFromFiles
could be defined as following:
const fs = require("fs");
const path = require("path");
const chalk = require("chalk");
const log = (key: string, msg: string, last: boolean = false) => {
const prefix = " " + (last ? "└──" : "├──");
console.log(`${prefix} ${chalk.grey(key)} : ${chalk.cyan(msg)}`);
};
const fromFiles = async (key, fileNames, handler) => {
for (const index in fileNames) {
const fileName = fileNames[index];
const filePath = path.join(dir, path.sep, fileName);
const contents = fs.readFileSync(filePath, "utf8").toString();
log(key, fileName, Number(index) === fileNames.length - 1);
await handler(contents);
}
};
module.exports.upFromFiles = async (dir, handler) => {
const fileNames = fs.readdirSync(dir);
await fromFiles("up", fileNames, handler);
};
module.exports.downFromFiles = async (dir, handler) => {
const fileNames = fs.readdirSync(dir).reverse();
await fromFiles("down", fileNames, handler);
}
Maybe if the package author agrees this code can be integrated with this package. If not and people do prefer to have this around for the taking. Then I might consider to publish into a separate package.